cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0 SPI slave transmitting random data

PJaco.2
Associate II

I have setup a STM32L0 as a slave to another micro. The ST must reply to the master with requested data received from a wireless source using SPI.

I can get the received data easily. The transmit is sending nonsense to the Master from the ST uC.

The master board was designed by another person who, unfortunately, decided to put 100kOhm resistors in-line with all the SPI lines. Because of this I had to lower the clock on the master to 32kHz!!! before I could actually receive anything.

I use the HAL drivers for this. I have tried the SPI_***_IT routines, SPI_***_DMA routines and and the blocking routines all with the same result. I have attached a screenshot of the data on the Miso line.

I am probably missing something but have no idea what to even look for anymore.

To test that the Tx does work I set the SPI as a Master and linked tx and Rx pins and in that way Tx worked perfectly - but I need slave mode. I am currently just Tx'ing a set string ("TestSPiTx")

Which I load into HAL_SPI_Transmit_DMA(&hspi1, SPITxBuffer, 9);

Main:

 /* USER CODE BEGIN 2 */

 strcpy(SPITxBuffer,"TestSPiTx");

// HAL_SPI_TransmitReceive_DMA(&hspi1, SPITxBuffer, SPIRxBuffer, 12); //Tried same result

 HAL_SPI_Transmit_DMA(&hspi1, SPITxBuffer, 9);

 HAL_SPI_Receive_DMA(&hspi1, SPIRxBuffer, 12);

 /* USER CODE END 2 */

 /* Infinite loop */

 /* USER CODE BEGIN WHILE */

 while (1)

 {

   /* USER CODE END WHILE */

   /* USER CODE BEGIN 3 */

 }

 /* USER CODE END 3 */

Initialization:

static void MX_SPI1_Init(void)

{

 /* USER CODE BEGIN SPI1_Init 0 */

 /* USER CODE END SPI1_Init 0 */

 /* USER CODE BEGIN SPI1_Init 1 */

 /* USER CODE END SPI1_Init 1 */

 /* SPI1 parameter configuration*/

 hspi1.Instance = SPI1;

 hspi1.Init.Mode = SPI_MODE_SLAVE;

 hspi1.Init.Direction = SPI_DIRECTION_2LINES;

 hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

 hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

 hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

 hspi1.Init.NSS = SPI_NSS_HARD_INPUT;

 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

 hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

 hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

 hspi1.Init.CRCPolynomial = 7;

 if (HAL_SPI_Init(&hspi1) != HAL_OK)

 {

   Error_Handler();

 }

 /* USER CODE BEGIN SPI1_Init 2 */

static void MX_DMA_Init(void)

{

 /* DMA controller clock enable */

 __HAL_RCC_DMA1_CLK_ENABLE();

 /* DMA interrupt init */

 /* DMA1_Channel2_3_IRQn interrupt configuration */

 HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);

 HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

}

 /* USER CODE END SPI1_Init 2 */

}

CallBack:

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)

{

//   HAL_SPI_Transmit_DMA(&hspi1, SPITxBuffer, 9);

   HAL_SPI_Transmit(&hspi1, SPITxBuffer, 9, 50);

}

HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)

{

   HAL_SPI_Receive_DMA(&hspi1, SPIRxBuffer, 12);

}

6 REPLIES 6
TDK
Guru

View those lines in analog mode to see if the edges on MISO are clean enough. Make sure you measure on the master-side of the 100kOhm resistors. Also may want to measure the SCK line where it enters the slave device.

> HAL_SPI_Transmit(&hspi1, SPITxBuffer, 9, 50);

This is almost certain to time out in slave mode, unless the master happens to be sending data during those 50ms. Shouldn't be calling blocking functions in an interrupt context anyway.

If you feel a post has answered your question, please click "Accept as Solution".
PJaco.2
Associate II

I can't say the signal is brilliant but I do get data...:>

Sorry that was supposed to have been commented out earlier. And you are correct, it didn't work. (I just needed to try everything)

PJaco.2
Associate II

It's almost as if the Tx is updating the bits too slow :persevering_face:

TDK
Guru

That signal is pretty awful, as you know. Looks like you have more than just the slow-rise time happening. Looks like there's cross talk with the SCK line as well, along with a few other spikes I can't really explain. Maybe crosstalk with other signals.

If you can't just replace those resistors with shunts or something much lower impedance, I would reduce your program to just:

while (1) {
  uint8_t c = 0xF0;  // (for example)
  HAL_SPI_Transmit(&hspix, &c, 1, HAL_MAX_DELAY);
}

and see what comes out. If it doesn't work well enough for a single character, it's hopeless for anything more complex. 100kOhm is a huge value, I'd focus on fixing that.

You don't show a CS line, but presumably you know the slave needs to be ready to send before you pull CS low and start sending clocks. Otherwise you're not going to be byte-aligned.

(Side note: The Saleae logic analyzer can do analog as well. At least mine can, but I think they all do. No need to bring a scope into it, at least not for signals for that low frequency.)

If you feel a post has answered your question, please click "Accept as Solution".
PJaco.2
Associate II

Thank you for the help TDK. The problem is with the clock line. It looks like a saw tooth. To prove a point to my manager, I removed the 100k resistor in line and now the Tx problem has been solved. So everything comes through correctly as it should. Massive amount of time wasting...

Now I need to do some signal conditioning and will most probably have to build some plugin board as our field technicians are not capable of replacing these resistors. So much fun 😂