2024-11-08 10:32 AM
I am using STM32H7B3I-DK running a touchgfx application and acting as SPI Master, and Nucleo-H743ZI as SPI Slave. Both are configured in interrupt mode not using HWNSS.
The Master is sending 0,1,2,3,4,5,6,7, but the slave is only receiving 0,2,4,6,0,2,4,6.
I am sending one byte at a time and receiving one byte then adding it to a buffer.
The master is properly sending data, as checked by oscilloscope. I have tried introducing a HAL-Delay(1) between transmissions and the data is then received perfectly fine; however, that is way to slow for proper communication. I have double checked the compatible settings for Master-Slave communication in the .ioc files such as Data Size, First Bit, etc...
Here is my following relevant code for the master:
for(;;)
{
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET); // Pull CS low
for (int i = 0; i < 8; i++) {
data[i] =i;
HAL_SPI_Transmit(&hspi2, &data[i], 1, HAL_MAX_DELAY); // Transmit one byte
HAL_UART_Transmit(&huart1, &data[i], 1, 0);
}
}
Here is the slave code:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_14) {
if (HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_14) == GPIO_PIN_RESET) {
HAL_SPI_Receive_IT(&hspi1, &rxBuffer[rxIndex], 1); // Start receiving
}
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
if ((hspi->Instance == SPI1) && (HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_14) == GPIO_PIN_RESET)) {
// Process received data
rxIndex = (rxIndex + 1) % RX_BUFFER_SIZE;
// Re-enable SPI interrupt for the next byte
HAL_SPI_Receive_IT(&hspi1, &rxBuffer[rxIndex], 1);
}
}
[...]
while (1)
{
for (int i = 0; i < 8; i++) {
printf("%u ", rxBuffer[i]);
}
printf("\n\r");
HAL_Delay(1000);
}
Solved! Go to Solution.
2024-11-08 12:08 PM
Close to impossible with HAL, still hard without.
2024-11-08 10:44 AM
Typical problem with SPI slave implementation. Either put come delay on master side between NSS low and transmit or call receive on slave side in advance, before NSS is detected active.
2024-11-08 10:56 AM
@gbm ,
Thank you for the suggestion, but I have already tried this. And I don't believe this to be the issue because the first byte is received fine. I just tried the following adding in a 1, 10, 100, and 1000ms delay before transmitting after nss low:
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_RESET); // Pull CS low
HAL_Delay(1000);
for (int i = 0; i < 8; i++) {
data[i] =i;
HAL_SPI_Transmit(&hspi2, &data[i], 1, HAL_MAX_DELAY); // Transmit one byte
HAL_UART_Transmit(&huart1, &data[i], 1, 0);
}
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0, GPIO_PIN_SET); // Pull CS high
2024-11-08 11:04 AM
That's really basic - it's not that easy to do SPI slave in an MCU. Call Receive for the whole packet once, not byte by byte. Otherwise you must introduce significant delays between bytes on master side. Also, make sure that you have the same SPI frame size set on both sides.
2024-11-08 11:09 AM - edited 2024-11-08 12:02 PM
@gbm ,
I was hoping to avoid that, as we are trying to use variable packet length. Is there not a way to receive just one byte at a time without the large delay?
2024-11-08 12:08 PM
Close to impossible with HAL, still hard without.
2024-11-15 12:58 AM
Hello @EthanMankins
To synchronize SPI communication, you can use a GPIO pin to ensure that the slave receive function is called before the master transmit function, you can follow these steps:
Slave Side:
Master Side: