问题
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