0

I am having troubles in interfacing the ICM20948 IMU with the HAL_layer of ST. My Master device (ST) is sending the data correctly to the slave (ICM) but the slave is not responding. I have checked very well every connection. I have tested several ICM's(3) and I have debugged it with my Logic analyser also (see pic below) I would really appreciate any help or pointer you could provide me.

My current setup is

enter image description here

The code its very simple I just have two simple read/write rotines

// --------------------------------------------------------------------------------------
/// \brief
///
/// \param *imu[in,out]: (IMU_def) IMU object with their respective ports
/// \param reg[in]: (uint8_t) register address
/// \param *pData[out]: (uint8_t) Data buffer
/// \return void
// --------------------------------------------------------------------------------------
void                    ICM_ReadOneByte                             (IMU_def *imu, uint8_t reg, uint8_t *pData)
{
    reg = reg | 0x80;                                                   // Make the MSB active to tell is a read see p31
    HAL_GPIO_WritePin(imu->CS_GPIO_Port, imu->CS_Pin, GPIO_PIN_RESET);  // Start transmission
    HAL_Delay(1);
    HAL_SPI_Transmit(imu->spi_bus, &reg, 1,1000);
    while (HAL_SPI_GetState(imu->spi_bus) != HAL_SPI_STATE_READY)           // TODO: Possible inf loop if slave don't answer. Counter?
        ;
    HAL_SPI_Receive(imu->spi_bus, pData, 1,1000);
    while (HAL_SPI_GetState(imu->spi_bus) != HAL_SPI_STATE_READY)           // TODO: Possible inf loop if slave don't answer. Counter?
        ;
    HAL_GPIO_WritePin(imu->CS_GPIO_Port, imu->CS_Pin, GPIO_PIN_SET);    // End transmission
}

// --------------------------------------------------------------------------------------
/// \brief
///
/// \param *imu[in,out]: (IMU_def) IMU object with their respective ports
/// \param reg[in]: (uint8_t) register address
/// \param Data[in]: (uint8_t) Data to write
/// \return void
// --------------------------------------------------------------------------------------
void                    ICM_WriteOneByte                            (IMU_def *imu, uint8_t reg, uint8_t Data)
{
    reg = reg & 0x7F;                                                   // Make the MSB disable to tell is a write see p31
    HAL_GPIO_WritePin(imu->CS_GPIO_Port, imu->CS_Pin, GPIO_PIN_RESET);  // Start transmission
    HAL_Delay(5);
    HAL_SPI_Transmit(imu->spi_bus, &reg, 1,1000);
    HAL_SPI_Transmit(imu->spi_bus, &Data, 1,1000);
    HAL_GPIO_WritePin(imu->CS_GPIO_Port, imu->CS_Pin, GPIO_PIN_SET);    // End transmission
}

In the main function I use the SPI_HandleTypeDef hspi2; instance to initialise an IMU object as

    imu.spi_bus      = &hspi2;
    imu.CS_GPIO_Port = GPIOB;
    imu.CS_Pin       = GPIO_PIN_4;

Just for testing that everything is fine I Just selected the BANK_0 and ask WHOIAM by

ICM_WriteOneByte(imu,USER_BANK_SEL, ICM_BANK_0); // USER_BANK_SEL (0x7F); USER_BANK_0:(0x00)
ICM_ReadOneByte(imu, 0x00, &whoami); // 

I have also try several steps in between when before calling WHOIAM() such as setting the reseting the device, Seting the internal clock, etc but nothing works. This is how I set other lines just in case:

ICM_WriteOneByte(imu,PWR_MGMNT_1, PWR_MGMNT_1_DEV_RESET); //PWR_MGMNT_1 (0x06);PWR_MGMNT_1_DEV_RESET:(0x80)
ICM_WriteOneByte(imu,PWR_MGMNT_1,PWR_MGMNT_1_CLOCK_SEL_AUTO);//(0x01)

In addition I also try NSS Disable (as is only one device) or Hardware(ST as output) but nothing changed.

Here is a picture of my Logic analyser enter image description here enter image description here

As you can see The Master is sending correctly the data to the slave but the slave is always High in the MISO line. I checked the frequency with my logic analyser and is bellow 7MHz as stated in the datashet

Nfalling 8 Nrising 8 fmin 3.846 MHz fmax 4.167 MHz fmean 3.977 MHz

Any Ideas are very welcome. Thanks!

SternK
  • 11,649
  • 22
  • 32
  • 46
FelipeM
  • 1
  • 2

1 Answers1

0

From the manual:

NOTE: To prevent switching into I2C mode when using SPI, the I2C interface should be disabled by setting the I2C_IF_DIS configuration bit. Setting this bit should be performed immediately after waiting for the time specified by the “Start-Up Time for Register Read/Write” in Section 6.3.

General Grievance
  • 4,555
  • 31
  • 31
  • 45