Showing results for 
Search instead for 
Did you mean: 

SPI periodically receiving wrong data

Associate II


I have a custom board with a STM32L010C6 MCU, which periodically reads 3 bytes (24 bit array) from an external component through SPI.

I only need SCLK and MISO since the frame resets using a timeout.

I configured the SPI as Only-Receiving Master, which didn't work OK. Now I am using the SPI peripheral as a Full-Duplex Master with software NSS and I perform data reads by polling function HAL_SPI_Receive().

It seems to work OK, with some delay between bytes.


The problem is that I periodically get bad data in the MCU. I identified that this happens when the SPI clock is not divided by 8-bit packets.


When this happens, the data transmitted by the external sensor is OK but the MCU doesn't read the correct value. In addition, I don't get any error state from the function, so I don't have a way to skip wrong values.

I tried reinitializing the SPI peripheral every time I want to perform a reading, but the problem persists.

Is there any reason which leads to this behaviour?


Associate III

You don't say in what way the data is wrong. Is is garbled bits, missing bytes, repeated bytes?

Obviously, since you a operating as spi master, as a work-around you could just force a pause between bytes.

>>I only need SCLK and MISO since the frame resets using a timeout.

Ok, so how does that maintain synchronization?

Typically the start of words / bytes is aligned to a CHIP SELECT (CS)

>>from an external component through SPI

What one? Does it have a data sheet? Does that set or express expectations?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

After digesting your issue, here my thoughts (steps to verify):

  1. You use nCS in SW mode - OK:
    Just check with a scope what happens with the other signals (esp. SCLK):
    Is SCLK still floating when nCS comes already? --> it would create false SCLK pulses on slave.
    Depending on how you use SPI in MCU - it can be that the SPI in MCU "releases the SPI bus" between transactions and SCLK is still floating when a new nCS comes.
    Use pull-up or pull-down to avoid (on SCLK, use the "inactive level" to tie up or down, or make sure SPI in MCU is driving all the time (not to disable SPI peripheral, not releasing the bus).
  2. The same for the end of transaction:
    Is nCS still low but SCLK starts to float? (SPI device in MCU releases the bus)
  3. Check, that you see always N times 8bit pulses: SPI does not work with "incomplete" words (bytes).
  4. Most likely what could happen:
    You have mentioned "frame resets using a timeout":
    What does it mean?:
    If you pause the Master SPI (no transfer, no SCLK) - the external chip would perform a reset?
    If so, you are not "in sync" with this chip:
    You can start a new Master SPI transaction when the chip is still doing a reset: it would lose a bit of the SPI transaction. All will be messed up (completely wrong, esp, an incomplete response to see and both sides can hang, if just one SCLK pulse was missing).
    To proof this: just make the duration between Master SPI transactions longer (assuming the external SPI chip is still in reset and not yet ready - give it more time).
    Potentially, it will work with a slower "polling speed" via SPI (if this is the root cause, I would guess).


Associate II

>>You don't say in what way the data is wrong. Is is garbled bits, missing bytes, repeated bytes?

In wrong reads, the bytes are shuffled.

>>Ok, so how does that maintain synchronization?

The synchronization is kept by using a minimum delay between samples. The clock signal is also used to detect when the frame starts so, after the frame timeout is reached, both sides of communication know the transaction is finished.

The proof that synchronization is kept OK without CS signal is that I have already solved the problem and it is working perfectly.


The problem was in the HAL function timeout. I was using a 1ms timeout since the frame timeout is about 100us, but it randomly triggered the function timeout too early. I set the timeout to HAL_MAX_DELAY since the MCU is the one who starts and ends the transaction and now it is working the right way. However, I have had to use a higher delay between samples (about 150us) to ensure the data is latched.