cancel
Showing results for 
Search instead for 
Did you mean: 

SPI - not recieving a response on MISO line

AndrasToth
Associate III

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:

AndrasToth_2-1713191910613.png

AndrasToth_3-1713191981610.png

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

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
AndrasToth
Associate III

 

I found a solution for this problem. It combines @AScha.3 suggestion with a little bit of a hardware tweaking. It seems that inspite of the statement from the datasheet that the device can tolerate 3.3V it doesn't like this voltage level. Therefore, I connected the lines with a voltage level translator to get 1.8V (I used LFS2040). With the following code I can read the correct value from the WhoAmI register (I can read 0x47 on the MISO):

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  TxData[0] = 0x80 | 0x75;
	  TxData[1] = 0x00;
	  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
	  HAL_SPI_TransmitReceive(&hspi1, TxData, RxData, 2, 50);
	  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  }
  /* USER CODE END 3 */

 Thank you very much for your helps and suggestions guys!

View solution in original post

20 REPLIES 20
MNapi
Senior III

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

 

Andrew Neil
Evangelist III

Have you used a logic analyser or oscilloscope to see what's actually happening on the wires?

The datasheet doesn't suggest any need for delays:

AndrewNeil_0-1713194625358.png

 

Uwe Bonnes
Principal III

Test your code on e.g. a Nucleo board and connect MOSI to MISO with a jumper wire.

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.

that's within the timing of the hardware peripheral - not a software delay between read & write.

AScha.3
Chief

Hi,

(after 30 mins on ds ...)

1. spi clk mode is wrong:

AScha3_0-1713198839245.png

set : cpol hi + cpha 2edge (as i see from this timing diagram)

AScha3_1-1713199138329.png

+ set in Cube/ioc : 

AScha3_3-1713200235542.png

 

2. command / response

AScha3_2-1713199377814.png

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.

 

If you feel a post has answered your question, please click "Accept as Solution".

Yes, I checked every line with oscilloscope and everything were working except the MISO line. On the MISO line I couldn't see anything.

I tried out your suggestion, but unfortunately it didn't work for me.