Skip to main content
Arthur S
Associate
May 9, 2018
Question

SPI in noisy environment - Techniques to mitigate spikes on CLK

  • May 9, 2018
  • 5 replies
  • 3570 views
Posted on May 09, 2018 at 15:02

Hi guys,

I'm using a STM32F303 micro controller in a noisy environment and there are some spikes on the SPI CLK line which mess up the functionality. The chip is used in slave mode and the SPI messages trigger a state machine. No CS line is employed, the slave is always listening. A spike on the clock line leads to a bitshift and thus false bit patterns or corrupted messages which leave my state machine corrupted. The clock is working at 1 MHz, data word length is 8 bit.

  • Is there a possibility to flush the fifo using a time out on the clock line? E.g. if the 8 clock ticks do not arrive after 10us flush the FIFO and reset the SPI state? I have not found any corresponding commands and deactivating and then again reactivating the SPI peripheral is too slow.
  • And as a more general question: How do I reset the SPI peripheral at all, without a timeout as described above? So how do I flush the FIFO and the registers holding the data? Is there a fast way doing that?

Im looking forward to your answers!

Best regards,

Arthur

SPI Init:

void MX_SPI2_Init(void)

{

  hspi2.Instance = SPI2;

  hspi2.Init.Mode = SPI_MODE_SLAVE;

  hspi2.Init.Direction = SPI_DIRECTION_2LINES;

  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi2.Init.NSS = SPI_NSS_SOFT;

  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi2.Init.CRCPolynomial = 7;

  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  if (HAL_SPI_Init(&hspi2) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }

}

SPI messages are sent and received via this command:

HAL_SPI_TransmitReceive_IT(&hspi2, (uint8_t *) tx_status, (uint8_t *) rx_status, 1);

#reset #flush #stm32f3 #noise #spi
This topic has been closed for replies.

5 replies

Arthur S
Arthur SAuthor
Associate
May 23, 2018
Posted on May 23, 2018 at 13:25

Has nobody an answer for me?

AvaTar
Senior III
May 23, 2018
Posted on May 23, 2018 at 14:20

A spike on the clock line leads to a bitshift and thus false bit patterns or corrupted messages which leave my state machine corrupted.

The SPI bus was designed as a flexible and simple on-board bus (on one PCB), with minimal costs (gates and chip area) and pin count. Like the I2C bus (Inter-IC Bus).

Electrical robustness comes at the cost of energy (higher currents/voltages) and gates (differential lines, level shifters, transceivers, etc.).

I would consider a more appropriate protocol.

I once participated in a project where SPI signals were transmitted over larger distances via optocouplers. Can't remember many details, except it was quite expensive, and died later for other reasons ...

T J
Senior III
May 23, 2018
Posted on May 23, 2018 at 14:52

SPI is a machine, it will do what you tell it to do.

If you add another clock source, you are screwed.

how long is your cable ?

the max pin current for a modern processor is 25mA.

if you used most of that, your noise immunity would be better, but not 100%

eg, 15mA, 3.3v V=IR, V/I = R

3.3 / 0.015 = 220R

So put a pull up 220R at the other end of the clock source.

Your need short wires for SPI, don't go past DC motors,  Switch modes. or High voltage.

Arthur S
Arthur SAuthor
Associate
May 24, 2018
Posted on May 24, 2018 at 13:06

Hi guys,

thank you for your answers. I'm using SPI over longer distances using differential drivers and optocouplers, similar to Application Note SLYT4441 from TI:

http://www.ti.com/lit/an/slyt441/slyt441.pdf

The bus has to be working in a noise environment, I cannot mitigate that. Additionally I know, when the spikes on the clock line happen, so all I need to do (at least that's what I think), is to flush the RCV FIFO or to reset the SPI peripheral after this moment in time.

I call the HAL_SPI_TransmitReceive_IT(&hspi2, (uint8_t *) tx_status, (uint8_t *) rx_status, 1); function after that moment, but the wrong information still gets clocked in. Then I tried just disabling the SPE (SPI enable) bit before this moment and setting it again afterwards: Then the SPI bus does not work any longer. Now I am using HAL_SPI_ABORT (which in my eyes seems to be huge and overloaded procedure) after this spike in order to get a clean, new starting point again - without effect.

Is there no simple procedure to tell the SPI peripheral to start anew, with both FIFOs empty? Going through the whole HAL_SPI_Deinit and then again HAL_SPI_Init(SPI_HandleTypeDef *hspi) cycle is too time consuming.

T J
Senior III
May 24, 2018
Posted on May 24, 2018 at 13:19

No, its a machine, 8 clock cycles out, per byte.

Your SPI transmitter is intact.

your receiver is confused

'Going through the whole HAL_SPI_Deinit and then again HAL_SPI_Init(SPI_HandleTypeDef *hspi) cycle is too time consuming.'

does that work ?

step through it, you will find the clearing counter mechanism if it exists.

You could use 2 diodes, if you want the slave to self detect and recover.

T J
Senior III
May 24, 2018
Posted on May 24, 2018 at 13:36

0690X0000060KuQQAU.png