Skip to main content
MSzos.1
Associate
July 2, 2020
Solved

Why is my SPI slave only sending one byte?

  • July 2, 2020
  • 5 replies
  • 3213 views

I am trying to read the position of an absolute rotary encoder (AMT22B-V). I have it connected to a Nucleo G474RE board. In the main.h file of the STM32CubeIDE project, I have the following declaration:

#define BUFFERSIZE            (COUNTOF(aTxBuffer) - 1)

In the main.c file, I have the following code:

uint8_t aTxBuffer[] = {0x00, 0x00};

uint8_t aRxBuffer[BUFFERSIZE];

HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE, 5000);

I am transmitting the 0x00 0x00 read command on MOSI and hoping to receive 2 bytes on MISO that describe the position of the encoder. However when I probe the lines with the logic analyzer function of my oscilloscope, I see that as I turn the encoder, only one byte is changing; the other one isn't changing. See image below. Also, I have the SPI data size set to 16 bits. I have a feeling that the issue has something to do with the BUFFERSIZE parameter. Any help is much appreciated.

0693W000001ryUzQAI.png

This topic has been closed for replies.
Best answer by berendi

Look at the timing diagram in the datasheet. It requires 2.5 µs delay between the two bytes.

Send one byte, wait 2.5 µs after the first byte is received, and send the second one, without raising CS# between them.

Mind the rest of the timing parameters too.

5 replies

berendi
berendiBest answer
Principal
July 2, 2020

Look at the timing diagram in the datasheet. It requires 2.5 µs delay between the two bytes.

Send one byte, wait 2.5 µs after the first byte is received, and send the second one, without raising CS# between them.

Mind the rest of the timing parameters too.

MSzos.1
MSzos.1Author
Associate
July 2, 2020

How do I delay it only 2.5 us? That seems like it would be too small for the HAL to accurately delay.

I think there are other issues with my code as well:

 HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)aTxBuffer[0], (uint8_t *)aRxBuffer[0], 1, 5000);

 HAL_Delay(0.0025);

 HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)aTxBuffer[1], (uint8_t *)aRxBuffer[1], 1, 5000);

waclawek.jan
Super User
July 2, 2020

Ah, that... sorry I did not read the original post carefully and was under the impression that the STM32 is the SPI slave... sorry for the confusion.

This is not trivial to pull out just by clicking in CubeMX and writing some HAL statements. The delay may presumably be longer, there's no max given. The usual way to handle this would be to combine timer (possibly interrupts) with SPI, an unorthodox and possibly bumpy road would be to pull this out entirely in SPI interrupt, by switching SPI clock pin to GPIO output for one byte transmitted in between the two "meaningful" bytes.

It may be easier to do this by avoiding SPI entirely, bitbanging it in a timer interrupt.

JW