cancel
Showing results for 
Search instead for 
Did you mean: 

Corrupted data via SPI_HAL_Receive in STM32F407

OVeli.1
Associate II

Dear friends, I need your help with the issue of data corruption when reading the data on SPI bus in STM32F407. I'm using 24 channels of temperature measurement (slaves) with one master STM32F407. 12 channels are connected to SPI1, other 12 channels - to SPI2.

Configuration of SPIs was done by CubeMX:

 hspi2.Instance = SPI2;
 hspi2.Init.Mode = SPI_MODE_MASTER;
 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.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
 hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi2.Init.CRCPolynomial = 10;
 
 hspi3.Instance = SPI3;
 hspi3.Init.Mode = SPI_MODE_MASTER;
 hspi3.Init.Direction = SPI_DIRECTION_2LINES;
 hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
 hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
 hspi3.Init.NSS = SPI_NSS_SOFT;
 hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
 hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
 hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi3.Init.CRCPolynomial = 10;

SPI CLK frequency is around 2.7 MHz. MAX31856 has maximum SPI clock at 5 MHz, so it is ok.

Code for reading the temperature:

	uint8_t byte_addr = 0x0C;
	uint8_t byte_rec_1[3] = {0};
	uint8_t byte_rec_2[3] = {0};
 
	for(temp_sens_t i = TEMP_SENS_1; i <= TEMP_SENS_12; i++)
	{
		chip_sel_temp_sens(11-i, ON);
		HAL_SPI_Transmit(&hspi1, &byte_addr, 1, 0xFFFF);
		HAL_SPI_Receive(&hspi1, byte_rec_1, 3, 0xFFFF);
		chip_sel_temp_sens(11-i, OFF);
		Temp_arr[11-i] = (int32_t)byte_rec_1[0] << 16;
		Temp_arr[11-i] |= (uint32_t)byte_rec_1[1] << 8;
		Temp_arr[11-i] |= (uint32_t)byte_rec_1[2];
 
		chip_sel_temp_sens(11-i, ON);
		HAL_SPI_Transmit(&hspi3, &byte_addr, 1, 0xFFFF);
		HAL_SPI_Receive(&hspi3, byte_rec_2, 3, 0xFFFF);
		chip_sel_temp_sens(11-i, OFF);
		Temp_arr[11-i+12] = (int32_t)byte_rec_2[0] << 16;
		Temp_arr[11-i+12] |= (uint32_t)byte_rec_2[1] << 8;
		Temp_arr[11-i+12] |= (uint32_t)byte_rec_2[2];
	}
}

Everything works fine for all channels, I can measure and control the temperature for all channels. But... Ocidentially, on some channels the data become incorrect. The analysis of the incorrect measured data and real data is in the attached file. I have connected two channels in parallel with one thermocouple, so it was possible to measure the same values for two separated MAX31856 ICs. So, as you can see, the first byte is read ok, but the second byte is incorrect for values lower than 128. Look like some higer bits are read as "1" instead of "0" - for the range 255...128 everything is correct, for the range 127...64 the eighth bit is wrong (1 instead of 0), for the range 63...32 - 8th and 7th bits are wrong, for the range 31...16 - 8th, 7th and 6th bits are wrong, etc.

I have analyzed the raw data on SPI bus by means of Logical Analyzer - the data is ok. In the Atollic I have set breakpoint on chip_sel_temp_sens(11-i, ON); line, where the data was just read by HAL function and that data is wrong...

As I said, such error is not regular - everything is ok in most cases, but, yesterday the 6th channel had such problem, today - 2nd channel (whereas 6th is ok).

Could you be so kind to help me with this issue?

3 REPLIES 3
OVeli.1
Associate II

Additional data - digged to the HAL_SPI_TransmitReceive and debugged the data, received from SPI buffer. In the *hspi->pTxBuffPtr is corrupted data. So, look like this is not a HAL issue...

    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* Check TXE flag */
      if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr);
        hspi->pTxBuffPtr++;
        hspi->TxXferCount--;
        /* Next Data is a reception (Rx). Tx not allowed */
        txallowed = 0U;
}

TDK
Guru

Your CPHA value doesn't match between the two.

 hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
...
 hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;

Intentional?

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

Sorry, it was a mistake in my description - 12 channels on SPI1, and another 12 channels - on SPI3. SPI1 and SPI3 has the same parameters except prescaller value. SPI2 is used for communication with another IC.

The problem was not in the firmware, but in the hardware. I'm using ADuM3154 for isolation between measurement and MCU parts, and when the second byte started to transmitt (HAL_SPI_Receive(&hspi1, byte_rec_1, 3, 0xFFFF);) glitch on the MISO somehow latched the signal MISO from ADuM3154 to MCU, so 2nd byte on MISO from MAX31856 to ADuM and from ADuM to MCU was different... Strange behaviour of ADuM, I must say...