2024-04-15 07:51 AM
Hello everyone!
I'm trying to communicate with a slave device (ICM-42688-P: https://invensense.tdk.com/wp-content/uploads/2020/04/ds-000347_icm-42688-p-datasheet.pdf), but I don't recieve anything on the MISO line. I'm using the nucleo-wb55rg for the master device. The ICM-42688 typically needs 1.8V for the VDD and VDDIO, but the datasheet says it can be used between the range of 1.71V and 3.6V. Therefore I just used the nucleo's 3.3V pin output to power both. After that I configured the SPI following the datasheet:
The code I wrote for excercise is a read from the whoAmI register, which is at address 0x75 and contains the value of 0x47. However I only get 0s from the MISO line.
The code from main.c:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USB_PCD_Init();
MX_MEMORYMAP_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
char spi_buff[16] = {0};
uint8_t addr = 0x00;
uint8_t data[2] = {0};
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
// Set bank addr 0x76
addr = 0x76;
data[1] = 0x00 | addr;
data[0] = 0x00;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)data, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
//Soft reset addr 0x11
addr = 0x11;
data[1] = 0x00 | addr;
data[0] = 0x01;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)data, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_Delay(1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// Get WhoIAM addr 0x75, value 0x47
addr = 0x75;
data[1] = 0x80 | addr;
data[0] = 0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)data, 2, 100);
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buff, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
/* USER CODE END 3 */
}
What am I missing here? Did I messed up something in the code or it is more likely a hardver issue?
I am looking forward for your answers!
Yours faithfully,
AndrasToth
2024-04-15 08:01 AM - edited 2024-04-15 08:17 AM
the most common problem is that you try to read too fast after sending command
try:
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, (uint8_t *)data, 2, 100);
HAL_Delay(100); //keep lowering delay to see if it still works or try higher setting
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buff, 2, 100);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
also try interrupt mode sometimes it works better
2024-04-15 08:21 AM
Have you used a logic analyser or oscilloscope to see what's actually happening on the wires?
2024-04-15 08:23 AM
The datasheet doesn't suggest any need for delays:
2024-04-15 08:24 AM
Test your code on e.g. a Nucleo board and connect MOSI to MISO with a jumper wire.
2024-04-15 08:58 AM - edited 2024-04-15 09:08 AM
look closer the SDO line is shifted a little bit to the right
so maybe you need only HAL_Delay(1) to do the job
he also deselects the chip too fast
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
before it can process the response.
if you are pounding it so fast in while() loop it might not work.
the response is never instantaneous it needs time to process data and request.
2024-04-15 09:34 AM
that's within the timing of the hardware peripheral - not a software delay between read & write.
2024-04-15 09:50 AM - edited 2024-04-15 09:57 AM
Hi,
(after 30 mins on ds ...)
1. spi clk mode is wrong:
set : cpol hi + cpha 2edge (as i see from this timing diagram)
+ set in Cube/ioc :
2. command / response
I would use :
/*HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size, uint32_t Timeout) */
uint8_t TxData[16], RxData[16];
so:
TxData[0] = 0x91 ; // read : whoami
HAL_SPI_TransmitReceive(&hspi1, TxData, RxData, 2 , 50);
The response should be in Rxdata[1] then.
3. set spi clk to 1 MHz or so, faster is no problem - if it works fine.
2024-04-17 03:41 AM
Yes, I checked every line with oscilloscope and everything were working except the MISO line. On the MISO line I couldn't see anything.
2024-04-17 03:43 AM
I tried out your suggestion, but unfortunately it didn't work for me.