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
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, ®, 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, ®, 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
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!