2020-07-21 02:02 AM
I am running a simple SPI transmit receive project with an STM32F411 (SPI Master) and STM32F303 (SPI Slave). Whenever I press the user push button on the STM32F4 Master, the Master will send a command byte (0xE1) through SPI and the STM32F3 Slave is expected to respond with 4 particular bytes. The snapshot of the logic analyzer below is what I expect to happen every single push button:
I could probably get the accurate SPI transaction above several times. However, most of the time, the snapshot below is what occurs:
After running through many tests, I am almost certain that the Slave is the issue because:
What is strange is that I use:
/* Exchange 4 bytes with SPI Master and store dummy bytes in pTempRxBuff */
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)pTxBuff, (uint8_t*)pTempRxBuff, cTxLen, 10000);
and receive part is working properly but the transmit part is not working properly.
I made sure that the CPOL, CPHA, MSB bit first, Baudrate Prescaler, APB2 clock speeds (on both STM32 boards), 8 bit datasize, and SPI Direction 2 Lines are the same between both boards.
I also configured the STM32F4 Master to run at 16MHz, while the STM32F3 Slave to run at 64MHz (with PLL) in hopes that the slave can process the data faster and be ready before the Master device clocks the SPI to retrieve the 4 bytes from the slave. It did not work as expected.
My main issue:
STM32F3 Slave does not send the right data most of the time (usually of by 1 bit in some of the bytes that are transmitted).
My SPI Slave (STM32F303) code:
This is my initialization code:
static void MX_SPI1_Init(void)
{
/* 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_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; // Recently added
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* Set spi interrupt priority and enable spi interrupts */
HAL_NVIC_SetPriority(SPI1_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
}
The data that I am sending:
#define RX_COMMAND_LENGTH 1
#define TX_LENGTH 4
static uint16_t cRxCmdLen = RX_COMMAND_LENGTH;
static uint16_t cTxLen = TX_LENGTH;
/* SPI Receive variables */
/* Command byte received to be stored in pRxBuff */
static volatile uint8_t pRxBuff[RX_COMMAND_LENGTH] = {0x00};
/* 4 dummy bytes to be stored in pTempRxBuff */
static uint8_t pTempRxBuff[TX_LENGTH] = {0x00, 0x00, 0x00, 0x00};
/* SPI Send variables */
/* temporary dummy value to be exchanged with the command byte */
static const uint8_t dummybyte[1] = {0x99};
/* 4 bytes to be sent to the Master */
static const uint8_t pTxBuff[TX_LENGTH] = {0xEB, 0x00, 0xCC, 0x01};
/* Exchange message flag for processing in main while loop */
volatile FlagStatus ExchangeMessage = RESET;
The SPI interrupt handler:
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
/* SPI1 peripheral used to exchange data with master device */
if(hspi->Instance == SPI1)
{
/* If command byte received is 0xE1 */
if(pRxBuff[0] == 0xE1)
{
/* Set volatile flag to high for processing 4 byte exchange in main loop */
ExchangeMessage = SET;
}
else
{
/* Ignore garbage data that was received */
/* Configure microcontroller to listen to other command bytes */
HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t*)dummybyte, (uint8_t*)pRxBuff, cRxCmdLen);
}
}
}
The main while loop:
while (1) {
if(ExchangeMessage == SET) {
/* Exchange 4 bytes with the master device */
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)pTxBuff, (uint8_t*)pTempRxBuff, cTxLen, 10000);
/* Reset volatile flag - this gets activated when a correct command byte is received*/
ExchangeMessage = RESET;
/* Configure microcontroller to start listening to command bytes again */
HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t*)dummybyte, (uint8_t*)pRxBuff, cRxCmdLen);
}
}
My SPI Master (STM32F411) Code:
Main while loop:
while (1) {
/* SendCmdByte is SET whenever a GPIO interrupt (push button) fires */
if(SendCmdByte == SET) {
/* Transmit first command byte 0xE1 */
uint8_t garbage[1] = {0x00}; // buffer for garbage value - expected: 0x99
HAL_SPI_Transmit(&hspi1, (uint8_t*)pTxBuff, cTxLen, spi_timeout);
/* Wait for end of spi transmission */
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
/* use i<150 for ~100 us delay to wait for slave to fill data*/
for(volatile uint16_t i=0; i<100; i++);
/* Transmit remaining 4 bytes of dummy value */
HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)pTempTxBuff, (uint8_t*)pRxBuff, cRxLen, spi_timeout);
/* Toggle LED after successfully exchanging bytes with dongle */
ToggleLed();
/* Reset received buffer values */
pRxBuff[0] = 0x00;
pRxBuff[1] = 0x00;
pRxBuff[2] = 0x00;
pRxBuff[3] = 0x00;
/* Reset volatile flag - this flag will be SET at every GPIO push button interrupt */
SendCmdByte = RESET;
}
}
My attempts at the problem:
What could be the problem here? Am I missing something with the SPI transaction? How do I solve this sync issue?
Any help would be greatly appreciated. Thank you!
Solved! Go to Solution.
2020-07-21 06:11 AM
It looks like the CPHA setting on your logic analyzer doesn't match the CPHA setting on your device. The waveforms are the same.
2020-07-21 06:11 AM
It looks like the CPHA setting on your logic analyzer doesn't match the CPHA setting on your device. The waveforms are the same.
2020-07-21 10:44 AM
I don't know how I missed this. I was too focused on the code that I forgot to consider how the logic analyzer configuration might be incorrect itself. Thank you for the solution!
Both of the code's configuration was CPOL = 0 and CPHA = 1 (2nd edge), but the logic analyzer was configured to CPOL = 0 and CPHA = 0. I am reading the correct waveforms now.
I do have a question regarding the logic analyzer's readings though. Why is it that when the logic analyzer is configured to CPOL = 0 and CPHA = 0, the readings are always different? I would imagine that if the configuration is wrong, the waveforms produced would be wrong but it would show the same incorrect data all the time.
2020-07-21 11:45 AM
2020-07-21 01:29 PM
I think I have a better understanding of the issue now. Thanks for the explanation!