2024-11-11 02:06 PM
Hello everyone,
I'm working on a project that involves UART communication between an STM32f429 and an nRF5340DK, with the nRF5340 acting as the UART transmitter and the STM32 as the receiver. However, I've been facing issues where the data received on the STM32 side appears to be out of sync, even though I’ve ensured that the baud rate and configuration match between both devices. Here are the details and what I've checked so far:
The STM32 receives data from the nRF5340DK, but the received data is frequently out of sync. Sometimes, it appears that characters are missing, or the data shifts unpredictably, leading to incorrect data interpretation on the STM32 side.
Double-Checked Baud Rate and Configurations: Both devices are set to the exact same UART configuration as listed above, including disabling flow control.
Examined Signal Integrity: I've checked the UART lines for noise or interference and verified that the wiring is secure, i noticed that logic high from the nordic board is around 2V but i don't think it's affecting the reading as the data is indeed received but just out of sync .
Buffer Handling on STM32: Ensured that the STM32 is ready to receive data and not missing characters due to buffer overruns.
Since the typical parameters (baud rate, parity, data bits, stop bits) all match,I'm note sure how to continue .
Has anyone experienced similar sync issues when connecting two microcontrollers via UART? I’d appreciate any advice on additional troubleshooting steps or alternative solutions that have worked for you.
Thanks in advance
2024-11-11 03:16 PM
You need to show code. No telling what HAL UART receive type you're using, what you're doing in the callback, etc..
2024-11-11 03:44 PM
The code is very basic just to prove the concept :
the init function :
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
#define RX_BUFFER_SIZE 12
/* Private variables ---------------------------------------------------------*/
uint8_t rx_buffer[RX_BUFFER_SIZE]; // Buffer to store received data
/* Function Prototypes */
void SystemClock_Config(void);
int main(void)
{
/* Initialize the HAL library and configure the system clock */
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_I2C1_Init();
/* Start UART reception in interrupt mode */
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
while (1)
{
// Main loop can perform other tasks or remain idle
HAL_Delay(1000); // Placeholder for other tasks or a low-power sleep mode
}
}
/* Callback function triggered when RX buffer is full */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) // Check if the interrupt is from USART1
{
// Echo the received data back for verification
// HAL_UART_Transmit(&huart1, rx_buffer, RX_BUFFER_SIZE, HAL_MAX_DELAY);
// Clear the buffer if needed
memset(rx_buffer, 0, RX_BUFFER_SIZE);
// Restart UART reception in interrupt mode
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
}
}
/* Error handler for UART */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
// Optionally handle errors (e.g., reinitialize or reset)
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
}
}
2024-11-11 04:18 PM
Re-edit your post and use the </> to post your code so that it's properly formatted and readable.
2025-02-05 06:16 AM
Let's assume that stm32 start receiving at the middle when nrf transmitted data. Which code does resync?
2025-02-05 06:29 AM
What data do you transfer to the STM32 (rhetorical question) ?
Debugging real-time is probably out of question.
I would suggest at first to enable interrupts on all receive errors, and just count them up.
Check later in a debugger.
Second, assuming you are transfering bursts / blocks / packages, add instrumentation code to buffer one or more of them in memory, for later inspection by a debugger.
And generally:
You are using a single-character receive interrupt, or DMA ?
I would use the interrupt method. 115200 bps can easily be managed in interrupt code.
DMA is quite troublesome for variable-length packages, and gets out of sync on every Rx error.
> However, I've been facing issues where the data received on the STM32 side appears to be out of sync, ...
This suggest you are using some kind of defined protocol, with distinct start and stop characters.
Always consider that either of them can get lost, and check the receive index for overflow.
2025-02-05 09:30 AM
Does the nRF5340DK always send 12 bytes? Is it binary or string data?
What are the example data (completed) you get from the nRF5340DK?
Knowing these things, we can come up with a better approach to receive the data.
Why would you send back what you received? Does the nRF5340DK required an echo of what it sent?
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
#define RX_BUFFER_SIZE 12
/* Private variables ---------------------------------------------------------*/
uint8_t rx_buffer[RX_BUFFER_SIZE]; // Buffer to store received data
/* Function Prototypes */
void SystemClock_Config(void);
int main(void)
{
/* Initialize the HAL library and configure the system clock */
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_I2C1_Init();
/* Start UART reception in interrupt mode */
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
while (1)
{
// Main loop can perform other tasks or remain idle
HAL_Delay(1000); // Placeholder for other tasks or a low-power sleep mode
}
}
/* Callback function triggered when RX buffer is full */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) // Check if the interrupt is from USART1
{
// Echo the received data back for verification
// HAL_UART_Transmit(&huart1, rx_buffer, RX_BUFFER_SIZE, HAL_MAX_DELAY);
// Clear the buffer if needed
memset(rx_buffer, 0, RX_BUFFER_SIZE);
// Restart UART reception in interrupt mode
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
}
}
/* Error handler for UART */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
// Optionally handle errors (e.g., reinitialize or reset)
HAL_UART_Receive_IT(&huart1, rx_buffer, RX_BUFFER_SIZE);
}
}
I assume this code below in the HAL_UART_RxCpltCallback was not commented out? This is blocking code. So while the HAL driver is transmitting, you will eventually be dropping data coming from the nRF5340DK
HAL_UART_Transmit(&huart1, rx_buffer, RX_BUFFER_SIZE, HAL_MAX_DELAY);
2025-02-05 10:06 AM - edited 2025-02-06 02:12 AM
As the others have said: what, exactly, do you mean by "out of sync" ?
Show examples.
What provisions do you have in your comms for synchronising?
PS:
Your UART handler as posted doesn't do anything useful at all:
/* Callback function triggered when RX buffer is full */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) // Check if the interrupt is from USART1
{
// Echo the received data back for verification
// HAL_UART_Transmit(&huart1, rx_buffer, RX_BUFFER_SIZE, HAL_MAX_DELAY);
// Clear the buffer if needed
memset(rx_buffer, 0, RX_BUFFER_SIZE);
// Restart UART reception in interrupt mode
HAL_UART_Receive_IT( &huart1, rx_buffer, RX_BUFFER_SIZE );
}
}
So how do you determine that it is "in sync" or "out of sync" (whatever they mean)?
Your main code just starts reception at an entirely arbitrary time - so how do you intend it to get "in sync" with the sender?
Please note How to insert source code.