Skip to main content
Graduate
March 6, 2022
Question

LSM6DSM on SensorTile using SPI?

  • March 6, 2022
  • 1 reply
  • 1646 views

I would like to know what I am doing wrong or what register setting on the LSM6DSM that I missed setting?

Using a sensorTile (STM32L476JG) that is connected to LSM6DSM. APB1 Clk = 16MHz.

My settings are :

0693W00000KbYP9QAN.png 

My code is trying to read WHO_AM_I register on the part, I get 0xC5 , should get 0x6A.

	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
	 txBuf[0] = 0x12;
	 txBuf[1] = 0x08;
	 HAL_SPI_Transmit(&hspi2, txBuf, 2, 50);
	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
 
	 /*
	 * disable i2c
	 */
	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
	 txBuf[0] = 0x13;
	 txBuf[1] = 0x04;
	 HAL_SPI_Transmit(&hspi2, txBuf, 2, 50);
	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
 
	 /*
	 * who_am_I : should return 0x6a
	 */
	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
	 txBuf[0] = 0x0F | 0x80;
	 HAL_SPI_Transmit(&hspi2, txBuf, 1, 50);
	 HAL_SPI_Receive(&hspi2, rxBuf, 1, 50);
	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);

    This topic has been closed for replies.

    1 reply

    ST Employee
    March 7, 2022

    Hi @SWenn.1​ ,

    I would suggest you to start by comparing your code with the SPI line configuration in the Sensortile firmware, i.e. the FP-SNS-ALLMEMS1 firmware function pack. You can refer to the two functions of the SensorTile_motion_sensors.c for:

    • Initializing of the SPI line:
    /**
     * @brief Initialize SPI bus for LSM6DSM
     * @retval BSP status
     */
    static int32_t BSP_LSM6DSM_Init(void)
    {
     GPIO_InitTypeDef GPIO_InitStruct;
     int32_t ret = BSP_ERROR_UNKNOWN_FAILURE;
     
     HAL_GPIO_WritePin(BSP_LSM6DSM_CS_PORT, BSP_LSM6DSM_CS_PIN, GPIO_PIN_SET);
     
     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     
     BSP_LSM6DSM_CS_GPIO_CLK_ENABLE();
     GPIO_InitStruct.Pin = BSP_LSM6DSM_CS_PIN;
     HAL_GPIO_Init(BSP_LSM6DSM_CS_PORT, &GPIO_InitStruct);
     HAL_GPIO_WritePin(BSP_LSM6DSM_CS_PORT, BSP_LSM6DSM_CS_PIN, GPIO_PIN_SET);
     
     if(BSP_SPI2_Init() == BSP_ERROR_NONE)
     {
     ret = BSP_ERROR_NONE;
     }
     
     return ret;
    }

    • SPI read function:
    /**
     * @brief Write register by SPI bus for LSM6DSM
     * @param Addr not used, it is only for BSP compatibility
     * @param Reg the starting register address to be written
     * @param pdata the pointer to the data to be written
     * @param len the length of the data to be written
     * @retval BSP status
     */
    static int32_t BSP_LSM6DSM_WriteReg(uint16_t Addr, uint16_t Reg, uint8_t *pdata, uint16_t len)
    {
     int32_t ret = BSP_ERROR_NONE;
     uint8_t dataReg = (uint8_t)Reg;
     
     /* CS Enable */
     HAL_GPIO_WritePin(BSP_LSM6DSM_CS_PORT, BSP_LSM6DSM_CS_PIN, GPIO_PIN_RESET);
     
     if (BSP_SPI2_Send(&dataReg, 1) != 1)
     {
     ret = BSP_ERROR_UNKNOWN_FAILURE;
     }
     
     if (BSP_SPI2_Send(pdata, len) != len)
     {
     ret = BSP_ERROR_UNKNOWN_FAILURE;
     }
     
     /* CS Disable */
     HAL_GPIO_WritePin(BSP_LSM6DSM_CS_PORT, BSP_LSM6DSM_CS_PIN, GPIO_PIN_SET);
     
     return ret;
    }

    By the way, are you always getting I get 0xC5 instead of 0x6A? Did you try to read other registers (such as the output regs after having configured at least the ODR in the control registers?)

    -Eleon

    SWenn.1Author
    Graduate
    March 7, 2022

    Hello Eleon....

    Thank you. I am not reading C5 consistently.....Sometimes 0xC5 sometimes 0x09....Never 0x6A. I did try to write a value to 0x25 to 0x71 address as well and there I receive back 0x09....I feel like I am missing some initializations on the LSM6DSM register settings?? As you can see I am setting register 0x12 (although I have no way to confirm that these writes are working......) which should set me for 3 wire SPI and register 0x13 which should disable I2C.....

    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
    	 txBuf[0] = 0x12;
    	 txBuf[1] = 0x08;
    	 HAL_SPI_Transmit(&hspi2, txBuf, 2, 50);
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
     
    	 /*
    	 * disable i2c
    	 */
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
    	 txBuf[0] = 0x13;
    	 txBuf[1] = 0x04;
    	 HAL_SPI_Transmit(&hspi2, txBuf, 2, 50);
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
     
    	 /*
    	 * who_am_I : should return 0x6a
    	 */
    /*
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
    	 txBuf[0] = 0x0F | 0x80;
    	 HAL_SPI_Transmit(&hspi2, txBuf, 1, 50);
    	 HAL_SPI_Receive(&hspi2, rxBuf, 1, 50);
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
    */
     
     
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
    	 txBuf[0] = 0x71;
    	 txBuf[1] = 0x25;
    	 HAL_SPI_Transmit(&hspi2, txBuf, 2, 50);
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
     
     
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
    	 txBuf[0] = 0x71 | 0x80;
    	 HAL_SPI_Transmit(&hspi2, txBuf, 1, 50);
    	 HAL_SPI_Receive(&hspi2, rxBuf, 1, 50);
    	 HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);

    ST Employee
    March 7, 2022

    Hi @SWenn.1​ ,

    but are you using the 3-wire SPI instead of the 4-wire standard? IN the first case you have to properly manage the SDI/O line, and also to write the SIM bit of the CTRL3_C (12h) register (but, if the SPI is not working, this action would not be possible).

    In this case, you might refer to the following piece of code:

    /**
    * @brief This function reads multiple bytes on SPI 3-wire.
    * @param xSpiHandle: SPI Handler.
    * @param val: value.
    * @param nBytesToRead: number of bytes to read.
    * @retval None
    */
    void LSM6DSM_SPI_Read_nBytes(SPI_HandleTypeDef* xSpiHandle, uint8_t *val, uint16_t nBytesToRead)
    {
     /* Interrupts should be disabled during this operation */
     __disable_irq();
     __HAL_SPI_ENABLE(xSpiHandle);
     
     /* Transfer loop */
     while (nBytesToRead > 1U)
     {
     /* Check the RXNE flag */
     if (xSpiHandle->Instance->SR & SPI_FLAG_RXNE)
     {
     /* read the received data */
     *val = *(__IO uint8_t *) &xSpiHandle->Instance->DR;
     val += sizeof(uint8_t);
     nBytesToRead--;
     }
     }
     /* In master RX mode the clock is automaticaly generated on the SPI enable.
     So to guarantee the clock generation for only one data, the clock must be
     disabled after the first bit and before the latest bit of the last Byte received */
     /* __DSB instruction are inserted to garantee that clock is Disabled in the right timeframe */
     
     __DSB();
     __DSB();
     __HAL_SPI_DISABLE(xSpiHandle);
     
     __enable_irq();
     
     while ((xSpiHandle->Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
     /* read the received data */
     *val = *(__IO uint8_t *) &xSpiHandle->Instance->DR;
     while ((xSpiHandle->Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY);
    }

    Note that if you want to read the WHO_AM_I register, you don't need a specific register setting, but only to initialize correctly the pins (Vdd, VddIO, SPI, GND).

    Could you try to setup the SPI-4 communication?

    -Eleon