cancel
Showing results for 
Search instead for 
Did you mean: 

Why is my SPI slave only sending one byte?

MSzos.1
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

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.

View solution in original post

5 REPLIES 5
berendi
Principal

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.

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);

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

Which datasheet? Where?

If you set SPI to 16-bit and then feed it with 8-bit data, C will zero-extend those data.

JW

This is the link to the datasheet. What do you mean by zero-extend?

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