Проблемы чтения данных из ADXL355 с использованием SPI (плата STM32) - PullRequest
1 голос
/ 27 февраля 2020

Я пытаюсь прочитать данные из EVAL-ADXL355-PMDZ, подключенного к комплекту обнаружения Lora STM2L072 через протокол SPI для проекта. Сначала я использовал датчик ADXL345 и смог прочитать данные акселерометра c и преобразовать их в g без каких-либо проблем. После переключения датчика на ADXL355 я продолжаю получать все нули при чтении регистров данных вместо этого.

Я изменил свой начальный код для ADXL345 в соответствии с таблицей данных датчика ADXL355 (https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_355.pdf), чтобы он мог работать с новым датчиком.

Основные изменения касаются настроек шины подключения SPI (ADXL345 использовал CPOL = 1 и CPHA = 1, а ADXL355 использует CPOL = 0 и CPHA = 0), имена регистров, количество байтов для чтения для каждой оси и коэффициент преобразования для преобразования необработанных данных в г. Я сохранил конфигурацию prescaler, которую я имел для ADXL345, где я установил его на 64, что дает мне скорость 500 Кбит / с c.

Также, по сравнению с ADXL345, бит R / W должен установить до младшего бита адреса, и я заметил, что бит многобайтового чтения не может быть установлен, но у меня есть некоторые сомнения по этому поводу, хотя, похоже, мне не нужно устанавливать его из таблицы данных (см. ссылку выше).

Это основной код (он инициализирует периферийные устройства и акселерометр и выполняет простое считывание данных l oop каждые 2 секунды):

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "string.h"

/* Private variables ---------------------------------------------------------*/
RTC_HandleTypeDef hrtc;

SPI_HandleTypeDef hspi2;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

uint8_t data[9]; /*Buffer to hold SPI data. Axis acceleration is a 20 bit value, and it's stored
in consecutive registers, from the most significative to the least significative data
and in left-justified mode. It is thus needed to read 3 bytes for each axis (i.e. 9 consecutive bytes
for each axis). */
int32_t x,y,z; /*variables that hold the binary acceleration reads. */
float xg, yg, zg; /*variables that hold the data converted in g. */
uint8_t data_tx[2];


uint8_t temp;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART2_UART_Init(void);

/* USER CODE BEGIN PFP */
//function to write 1 byte in a register on the accelerometer  through SPI
//void SPI_write(uint8_t address, uint8_t value);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void SPI_write (uint8_t address, uint8_t value) //function to write 1 byte in a register on the accelerometer  through SPI
{

    data_tx[0]= (address<<1) | 0x00; /* set write operation= to enter Write mode you have to set the 8th bit of the first byte sent to 0.*/
    data_tx[1] = value; /*byte to write in the register*/
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);  // pull the CS pin (PA12) low (selects the slave)
    HAL_SPI_Transmit (&hspi2, data_tx, 2, 100);  // write data to register specifying that it consists of 2 bytes (address+value)
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);  // pull the CS pin high
}

void SPI_read (uint8_t address, int bytes) //function to read multiple bytes from a register on the accelerometer through SPI
{
    address = (address<<1) | 0x01;  /* set read operation= to enter Read mode you have to set the 8th bit of the first byte sent to 1.*/
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);   // pull the CS pin low
    HAL_SPI_Transmit (&hspi2, &address, 1, 100);  // send address
    HAL_SPI_Receive (&hspi2, data, bytes, 100);  // receive the data
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);   // pull the CS pin high
}

void adxl_init(void){
    //Configuring the Range
    SPI_write(0x2C, 0x02);  /*b00000001=0x01 in 0x2C register (Interrupt Polarity, Range register)
    sets a 4g range. The ADXL also uses 20 bit RES and stores data in the left-justified mode.*/

    //Configuring the Power Control or POWER_CTL register:
    SPI_write(REG_POWER_CTL, 0x06); /* enters measurement mode and disables temperature reading */
}


void display_Data(double val, char axis){ //displays acceleration data using UART
    char msg[20];
    sprintf(msg, "%c: %f",axis, val);
    HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);
    char newline[2] = "\r\n";
    HAL_UART_Transmit(&huart2, (uint8_t *) newline, 2, 10);
}

void readSensor(void){
    SPI_read(0x08, 9); /*the full accelerometer information is held in 3 bytes for each axis, so you need to read 9 bytes
    (also, acceleration data is stored from the most significant bit to the least significant one) */

    // copy the 3 bytes received for each axis into a single variable
    x=((data[0]<<16) | (data[1]<<8) | data[2]) >>4; /*moving the first received byte at the beginning (left-justified),
    then using an OR to concatenate it with the second byte (shifted the same way) and lastly the third byte
    Since this are 20-bits values, we then shift the copied value 4 bits to the right*/
    y=((data[3]<<16) | (data[4] <<8) | data[5]) >>4;
    z=((data[6]<<16) | (data[7] <<8) | data[8]) >>4;
    //converting to g
    /* From the datasheet we get that for a +-4g sensitivity the scale factor is 7.8 ug/LSB.
     * To convert the data we just need to multiple with 7.8 and then divide by 1000000*/
    xg=x*0.0000078;
    yg=y*0.0000078;
    zg=z*0.0000078;
}

int check_adxl(void){
    SPI_read(0x01, 1);
    temp=(uint8_t)data[0];
    return (temp==0x1D);
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_SPI2_Init();
  MX_USART2_UART_Init();
  //HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); //sets CS line high when not reading/writing
  /* USER CODE BEGIN 2 */
  HAL_Delay(1000);
  adxl_init();
  char *mex="Accelerometer...";
  char line[2] = "\r\n";
  HAL_UART_Transmit(&huart2, (uint8_t *) mex, 15, 10);
  HAL_UART_Transmit(&huart2, (uint8_t *) line, 2, 10);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
      HAL_Delay(2000);
       /*Reading and displaying sensor data*/
      readSensor();
      display_Data(xg, 'X');
      display_Data(yg, 'Y');
      display_Data(zg, 'Z');

      HAL_UART_Transmit(&huart2, (uint8_t *) line, 2, 10);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Это моя конфигурация SPI для ADXL355 (выполненная с использованием STM32CubeMX):

static void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 7;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

Результат, который я получаю, всегда равен нулю. Кроме того, если я пытаюсь прочитать другие регистры, я получаю либо 0, либо 255, поэтому я предполагаю, что проблема в соединении SPI.

Я проверял соединения тысячу раз, и они должны быть правильными (это документация, которую я использовал https://wiki.analog.com/resources/eval/user-guides/eval-adicup360/hardware/adxl355).

Я видел некоторые другие подобные проблемы, подобные этой Чтение данных из ADXL355 с использованием python интерфейса SPI на Raspberry Pi (даже если этот использует малину), и мне было интересно, может ли ADXL355 возможно есть проблемы?

Заранее спасибо за любую помощь по этому вопросу.

...