Issues reading data from ADXL355 using SPI (STM32 board)

半城伤御伤魂 提交于 2020-04-16 03:33:46

问题


I'm trying to read data from an EVAL-ADXL355-PMDZ connected to a STM2L072 Lora discovery kit through the SPI protocol for a project. At first I was using an ADXL345 sensor and I was able to read the accelerometric data and convert it to g without any issues. After switching the sensor to ADXL355, I keep receive all zeroes when reading data registers instead.

I changed my initial code for ADXL345 accordingly to the datasheet of the ADXL355 sensor (https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_355.pdf) so that it could work with the new sensor.

The main changes involve the settings for the SPI connection bus (ADXL345 used CPOL=1 and CPHA=1, while ADXL355 uses CPOL=0 and CPHA=0), the registers names, the number of bytes to read for each axis and the conversion factor to convert raw data to g. I kept the prescaler configuratoin I had for ADXL345, where I had set it to 64, giving me a 500 Kbits/sec speed.

Also, compared to the ADXL345, the R/W bit needs to be set before the LSB of the address and I noticed there's no multibyte-read bit to be set, but I have some doubts about this even though it looks like I don't need to set it from the datasheet (see link above).

This is the main code (it initializes the peripherals and the accelerometer and it realizes a simple loop reading data every 2 seconds):

/* 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 */
}

This is my SPI configuration for the ADXL355 (done using 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 */

}

The result I get is always zero though. Also, if I try to read other registers, I either get 0 or 255, so I guess the SPI connection is the problem.

I checked the connections a thousand times and they should be right (this is the documentation I used https://wiki.analog.com/resources/eval/user-guides/eval-adicup360/hardware/adxl355).

I saw some other similar issues like this Read data from ADXL355 using python SPI interface on raspberry pi (even though this one used a raspberry) and I was wondering if the ADXL355 might have problems maybe?

Thanks in advance for any help about this issue.

来源:https://stackoverflow.com/questions/60438866/issues-reading-data-from-adxl355-using-spi-stm32-board

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!