使用SPI(STM32板)从ADXL355读取数据时出现问题

时间:2020-02-27 17:34:34

标签: embedded stm32 accelerometer spi firmware

我正在尝试通过SPI协议从连接到STM2L072 Lora发现套件的EVAL-ADXL355-PMDZ中读取数据。最初,我使用的是ADXL345传感器,能够读取加速度数据并将其转换为g,没有任何问题。将传感器切换到ADXL355之后,在读取数据寄存器时,我一直接收全零。

我已根据ADXL355传感器(https://www.analog.com/media/en/technical-documentation/data-sheets/adxl354_355.pdf)的数据表更改了ADXL345的初始代码,以便它可以与新传感器一起使用。

主要更改涉及SPI连接总线的设置(ADXL345使用CPOL = 1和CPHA = 1,而ADXL355使用CPOL = 0和CPHA = 0),寄存器名称,每个轴要读取的字节数以及将原始数据转换为g的转换因子。我保留了ADXL345的预分频器可配置性,将其设置为64,使我的速度为500 Kbits / sec。

此外,与ADXL345相比,需要在地址的LSB之前设置R / W位,我注意到没有要设置的多字节读取位,但是我对此有一些疑问即使看起来好像我不需要从数据表中进行设置(请参阅上面的链接)。

这是主要代码(它初始化外围设备和加速度计,并实现每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 */
}

这是我的ADXL355的SPI配置(使用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)。

我看到了类似Read data from ADXL355 using python SPI interface on raspberry pi这样的其他类似问题(即使该问题使用了覆盆子),我想知道ADXL355是否可能有问题?

预先感谢您提供有关此问题的帮助。

1 个答案:

答案 0 :(得分:3)

也许你已经发现了这个问题。我注意到您没有考虑到数据值的格式为二进制补码。要解决此问题,请在此处检查函数 ADXL355_Acceleration_Data_Conversionhttps://github.com/analogdevicesinc/EVAL-ADICUP360/blob/master/projects/ADuCM360_demo_adxl355_pmdz/src/ADXL355.c