Skip to main content
Explorer
November 11, 2024
Question

UART Communication Sync Issues Between STM32 and nRF5340DK

  • November 11, 2024
  • 4 replies
  • 2146 views

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:

Hardware Setup

  • Microcontrollers: nRF5340DK (Nordic Semiconductor) and STM32 (STMicroelectronics).
  • Connections: Direct UART lines (TX from nRF5340 to RX on STM32, and RX from nRF5340 to TX on STM32 for debugging, if needed).
  • UART Configuration:
    • Baud Rate: 115200
    • Data Bits: 8
    • Stop Bits: 1
    • Parity: None
    • Flow Control: Disabled (enabled it to see if it makes any diffrence but no diffrence observed)

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.

Steps I’ve Taken So Far

  1. Double-Checked Baud Rate and Configurations: Both devices are set to the exact same UART configuration as listed above, including disabling flow control.

  2. 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 .

  3. 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 

    This topic has been closed for replies.

    4 replies

    Graduate II
    November 11, 2024

    You need to show code. No telling what HAL UART receive type you're using, what you're doing in the callback, etc..

    AnassoumiAuthor
    Explorer
    November 11, 2024

    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);

    }

    }

     

     

     

     

     

    Graduate II
    November 12, 2024

    Re-edit your post and use the </> to post your code so that it's properly formatted and readable.

    Graduate II
    February 5, 2025

    Let's assume that stm32 start receiving at the middle when nrf transmitted data. Which code does resync?

    Explorer
    February 5, 2025

    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.

    Super User
    February 5, 2025

    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.