2021-03-13 10:41 PM
I have tried to work with LIS3DSH sensor using SPI protocol. I applied procedures on STM32L0 Discovery kit LoRa. But it didn't work.
My problem is The LIS3DSH x-y-z-axis output value is invalid and the value is not changed. No matter which direction I rotate the device but I check ID of LIS3DSH is correct ( 0011 1111)
Component
- STM32L0 Discovery kit LoRa
- LIS3DSH (https://www.amazon.com/LIS3DSH-High-Resolution-Three-axis-Accelerometer-Triaxial/dp/B07QS5D9K9/ref=sr_1_4?dchild=1&keywords=LIS3DSH&qid=1615701212&sr=8-4)
----
init SPI2
void HW_SPI2_Init(void)
{
/*##-1- Configure the SPI2 peripheral */
/* Set the SPI parameters */
hspi2.Instance = SPI2;
hspi2.Init.BaudRatePrescaler = SpiFrequency(10000000);
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; // CPHA = 1
// hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA = 0
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
// hspi2.Init.DataSize = SPI_DATASIZE_16BIT;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCPolynomial = 10;
SPI2_CLK_ENABLE(); // Enable clock for SPI 2
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the SPI GPIOs */
HW_SPI2_IoInit();
}
Set PIN
void HW_SPI2_IoInit(void)
{
GPIO_InitTypeDef initStruct = {0};
initStruct.Mode = GPIO_MODE_AF_PP;
initStruct.Pull = GPIO_PULLUP ;
initStruct.Speed = GPIO_SPEED_FAST;
initStruct.Alternate = SPI2_AF;
HW_GPIO_Init(LIS3DH_SCLK_PORT, LIS3DH_SCLK_PIN, &initStruct);
HW_GPIO_Init(LIS3DH_MISO_PORT, LIS3DH_MISO_PIN, &initStruct);
HW_GPIO_Init(LIS3DH_MOSI_PORT, LIS3DH_MOSI_PIN, &initStruct);
initStruct.Mode = GPIO_MODE_OUTPUT_PP;
initStruct.Pull = GPIO_NOPULL;
HW_GPIO_Init(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, &initStruct);
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}
initialization LIS3DSH
void LIS3DSH_DH_initialization (void)
{
uint8_t au8LISConfig[2];
#if defined(IC_LIS3DH)
#elif defined(IC_LIS3DSH)
/********************************************
* Config CTRL_REG4
********************************************/
au8LISConfig[0] = LIS3Dx_CTRL_REG4_ADDR;
au8LISConfig[1] = 0x67;
HW_SPI2_CS_ON();
HW_SPI2_2byte_Write(au8LISConfig);
HW_SPI2_CS_OFF();
/********************************************
* Config CTRL_REG3
********************************************/
au8LISConfig[0] = LIS3Dx_CTRL_REG3_ADDR;
au8LISConfig[1] = 0xC8;
HW_SPI2_CS_ON();
HW_SPI2_2byte_Write(au8LISConfig);
HW_SPI2_CS_OFF();
/********************************************
* Config OFFSET X
********************************************/
au8LISConfig[0] = LIS3DSH_OFF_X_ADDR;
au8LISConfig[1] = 0x00;
HW_SPI2_CS_ON();
HW_SPI2_2byte_Write(au8LISConfig);
HW_SPI2_CS_OFF();
/********************************************
* Config OFFSET Y
********************************************/
au8LISConfig[0] = LIS3DSH_OFF_Y_ADDR;
au8LISConfig[1] = 0x00;
HW_SPI2_CS_ON();
HW_SPI2_2byte_Write(au8LISConfig);
HW_SPI2_CS_OFF();
/********************************************
* Config OFFSET Z
********************************************/
au8LISConfig[0] = LIS3DSH_OFF_Z_ADDR;
au8LISConfig[1] = 0x00;
HW_SPI2_CS_ON();
HW_SPI2_2byte_Write(au8LISConfig);
HW_SPI2_CS_OFF();
#endif
}
CS ON or OFF
void HW_SPI2_CS_ON (void)
{
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 0);
}
void HW_SPI2_CS_OFF (void)
{
HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}
Read ID
uint8_t LIS3DSH_DH_CHECK_ID (void)
{
uint8_t addr = LIS3Dx_WHO_AM_I_ADDR | LIS3Dx_READ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
UsingTypeint_LIS3DSH_DH.ID = au8BufferRead_SPI2[0];
return UsingTypeint_LIS3DSH_DH.ID;
}
Read X axis ( only)
void LIS3DSH_DH_GET_XYZ (void)
{
uint8_t addr = LIS3Dx_OUT_X_L_ADDR | LIS3Dx_READ ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
addr = LIS3Dx_OUT_X_H_ADDR | LIS3Dx_READ ;
HW_SPI2_CS_ON();
HW_SPI2_SPI_1byte_Write_and_Read(addr);
HW_SPI2_CS_OFF();
}
HW_SPI2_1byte_Write_and_Read
bool HW_SPI2_SPI_1byte_Write_and_Read(uint8_t u8Address)
{
if(HAL_SPI_Transmit(&hspi2, (uint8_t *)&u8Address, 1, HAL_MAX_DELAY) == HAL_OK){
if(HAL_SPI_Receive(&hspi2, (uint8_t *)&au8BufferRead_SPI2[0], 1, HAL_MAX_DELAY) == HAL_OK){
return true;
}
}
return false;
}
LIS3DSH and STM
X L axis (adress 0x28)
X H axis (adress 0x29)
LIS3DSH Header
//List of Defines
/* ****************************************************
*
* L - I - S - 3 - D - S - H
*
* registers addresses
**************************************************** */
#define LIS3Dx_READ 0x80
#define LIS3Dx_WRITE 0x00
#define LIS3Dx_WHO_AM_I_ADDR 0x0F
#define LIS3Dx_ID 0x3F
/* LIS3DSH ONLY [0x0C] */
#define LIS3DSH_CTRL_REG0_ADDR 0x0C // Read
/* LIS3DSH ONLY [0x0D-0x0E] */
#define LIS3DSH_INFO1_ADDR 0x0D // Read | Default 0010 0001
#define LIS3DSH_INFO2_ADDR 0x0E // Read | Default 0000 0000
/* LIS3DSH ONLY [0x10-0x12] */
#define LIS3DSH_OFF_X_ADDR 0x10 // Read/Write | Default 0000 0000
#define LIS3DSH_OFF_Y_ADDR 0x11 // Read/Write | Default 0000 0000
#define LIS3DSH_OFF_Z_ADDR 0x12 // Read/Write | Default 0000 0000
/* LIS3DSH ONLY [0x10-0x12] */
#define LIS3DSH_CS_X_ADDR 0x13 // Read/Write | Default 0000 0000
#define LIS3DSH_CS_Y_ADDR 0x14 // Read/Write | Default 0000 0000
#define LIS3DSH_CS_Z_ADDR 0x15 // Read/Write | Default 0000 0000
/* LIS3DSH ONLY [0x16-0x17] */
#define LIS3DSH_LC_L_ADDR 0x16 // Read/Write | Default 0000 0001
#define LIS3DSH_LC_L_ADDR 0x17 // Read/Write | Default 0000 0000
/* LIS3DSH ONLY [0x18] */
#define LIS3DSH_STAT_ADDR 0x18 // Read
/* LIS3DSH ONLY [0x19-0x1A] */
#define LIS3DSH_PEAK1_ADDR 0x19 // Read
#define LIS3DSH_PEAK1_ADDR 0x1A // Read
/* LIS3DSH ONLY [0x1B-0x1E] */
#define LIS3DSH_VFC_1_ADDR 0x1B // Read/Write
#define LIS3DSH_VFC_2_ADDR 0x1C // Read/Write
#define LIS3DSH_VFC_3_ADDR 0x1D // Read/Write
#define LIS3DSH_VFC_4_ADDR 0x1E // Read/Write
/* LIS3DSH ONLY [0x1F] */
#define LIS3DSH_THRS3_ADDR 0x1F // Read/Write
#define LIS3Dx_CTRL_REG1_ADDR 0x21 // Read/Write | Default 0000 0111
#define LIS3Dx_CTRL_REG2_ADDR 0x22 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG3_ADDR 0x23 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG4_ADDR 0x20 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG5_ADDR 0x24 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG6_ADDR 0x25 // Read/Write | Default 0001 0000
#define LIS3Dx_STATUS_ADDR 0x27
#define LIS3Dx_OUT_X_L_ADDR 0x28 // Read/Write | Default 0000 0000
#define LIS3Dx_OUT_X_H_ADDR 0x29
#define LIS3Dx_OUT_Y_L_ADDR 0x2A
#define LIS3Dx_OUT_Y_H_ADDR 0x2B
#define LIS3Dx_OUT_Z_L_ADDR 0x2C
#define LIS3Dx_OUT_Z_H_ADDR 0x2D
#define LIS3Dx_FIFO_CTRL_REG_ADDR 0x2E // Read/Write | Default 0000 0000
#define LIS3Dx_FIFO_SRC_REG_ADDR 0x2F // Read
Global
typedef struct
{
uint8_t dataRate;
uint8_t fullScale;
uint8_t antiAliasingBW;
uint8_t enableAxes;
bool interruptEnable;
}LIS3DSH_InitTypeDef;
//2. Accelerometer raw data
typedef struct
{
int16_t x;
int16_t y;
int16_t z;
}LIS3DSH_DataRaw;
//3. Accelerometer mg data (scaled data)
typedef struct
{
float x;
float y;
float z;
}LIS3DSH_DataScaled;
extern LIS3DSH_InitTypeDef myAccConfigDef;
2021-03-16 08:25 AM
Hi @PChar.1 ,
If you are able to correctly read the WHO_AM_I value, but the data out are all 00h (or FFh? or fixed to a certain value), there might be an issue related to the configuration of the device, especially in the initialization procedure.
You correctly used the LIS3DSH initialization in the application note AN3393, so I would suggest you to check if these registers have been correctly written by reading them after their setting.
You can also check the C drivers on Github repository, for example the lis3dsh_read_data_polling.c. In particular, here the ADD_INC bit of register CTRL_REG6 (25h) and the BDU bit of CTRL_REG4 (20h) registers (so, 6Fh instead of 67h) have ben set.
/* Set bdu and if_inc recommended for driver usage */
lis3dsh_init_set(&dev_ctx, LIS3DSH_DRV_RDY);
/* Set Output Data Rate */
lis3dsh_mode_get(&dev_ctx, &md);
md.fs = LIS3DSH_4g;
md.odr = LIS3DSH_25Hz;
lis3dsh_mode_set(&dev_ctx, &md);
By the way, are you performing multiple or single SPI reading?
-Eleon
2021-07-15 11:36 PM
Hi!
Polarity of SPI clock is actually HIGH. Set CPOL = 1 in your SPI configuration, then it should work :).
Also word size is 16 bit, look at datasheet figure 7.
Correct config for SPI is:
CPOL = 1
CPHA = 1
Word size = 16 bit