2018-05-09 06:02 AM
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.
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 #spi2018-05-23 04:25 AM
Has nobody an answer for me?
2018-05-23 05:20 AM
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 ...
2018-05-23 05:52 AM
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.
2018-05-24 04:06 AM
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.
2018-05-24 04:36 AM
2018-05-24 06:19 AM
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.
2018-05-24 06:31 AM
I would abandon the idea to use SPI, and switch to UART/USART instead, probably using RS485.
This has the advantage of a defined character transmission length/timing. You get an error flag if the transmission is corrupted.
You can transfer in packages with defined start characters, end characters, and perhaps pause intervals. This allows for an easier re-synchronization after transmission errors.
And you can include a checksum, and a re-transmission request, if you need complete and correct transfers.
Just a suggestion.
2018-05-25 04:05 AM
Thank you for the idea! In my eyes UART was pretty slow or too slow, but reading a bit about RS485 my knowledge seems to be outdated. As I built my bus similar to the application note cited above, it could be possible to switch to RS485 without too much changes. I have to take some time and look deeper into that.
2018-05-25 04:30 AM
It does not necessarily have to be UART.
But a defined (and time-limited/terminated) character transmission seems crucial in your environment.
And RS485 uses higher signal energy levels, which are less affected by EMI.
CAN would be another (more complex and expensive) candidate.