LIS3DSH x y z axis is incorrect

Viewed 187

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

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();
}

...

initialization LIS3DSH

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);
}

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) (Incorrect)

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;
}

Signal

output X L

output X H

1 Answers

Am not sure if you are using the state machine and register accesses of the LIS3DSH accurately.

As a reference see the register mapping in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.h (start at line 95) and the code in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.c

The function that actually writes and reads the SPI bus is void ACCELERO_IO_Write(uint8_t *pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) and void ACCELERO_IO_Read(uint8_t *pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)

This is defined in https://documentation.help/STM32F4-Discovery-BSP/stm32f4__discovery_8c_source.html at lines 560 and 594

In void ACCELERO_IO_Write(uint8_t *pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) the actual SPI write is done at lines 574 to 582

00574   SPIx_WriteRead(WriteAddr);  

00577   while(NumByteToWrite >= 0x01)
00578   {
00579     SPIx_WriteRead(*pBuffer);
00580     NumByteToWrite--;
00581     pBuffer++;
00582   }

(as always with SPI first activate register, then write data...)

In SPIx_WriteRead(WriteAddr); the WriteAddr is taken from the register mapping in https://github.com/STMicroelectronics/stm32-lis3dsh/blob/main/lis3dsh.h, start at line 9

(the above code by STM for the LIS3DSH is nice work, this implementation is very clean and structured)

The datasheet of the LIS3DSH is in https://www.st.com/resource/en/datasheet/lis3dsh.pdf, the reference manual is far more detailed it is in https://www.st.com/resource/en/application_note/dm00026768-lis3dsh-3axis-digital-output-accelerometer-stmicroelectronics.pdf it also includes explanation of the state machines, that have to be configured before the device works

Related