Skip to main content
Explorer II
January 15, 2025
Question

STM32 UART does not receive first byte

  • January 15, 2025
  • 3 replies
  • 1094 views

MCU: STM32L476RGT6

Hello,

I am using UART to read data from the NEO-M9N GPS receiver. My receive buffer stores all received data besides the first byte:

received_GPS.pngReceived_GPS2.png

This forum states to add a delay between initializing UART and sending data, and this forum states to clear the buffer before transmitting data. However, neither solution works for me. These forums are addressing an issue where the first byte received is 0x00. However, my issue is that rather than receive 0x00, I skip the first byte entirely.

Any tips on how to fix this would be appreciated. Thanks.

static void MX_USART3_UART_Init(void);
UART_HandleTypeDef huart3;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
uint8_t buffer[100];
uint8_t buffer_idx;

int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
buffer_idx=0;
while(HAL_TIMEOUT != HAL_UART_Receive(&huart3, buffer, 1, 10));
HAL_UART_Receive_IT(&huart3, buffer, 1);
HAL_Delay(1);
while (1) {
uint8_t arr[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30};
HAL_UART_Transmit(&huart3, arr, sizeof(arr), HAL_MAX_DELAY);
HAL_Delay(100);
buffer_idx=0;
HAL_Delay(1000);
}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_IT(&huart3, buffer+buffer_idx, 1);
buffer_idx++;
}

 

    This topic has been closed for replies.

    3 replies

    Graduate II
    January 15, 2025

    You set buffer_idx to 0 but the callback of last byte of the previous reception already called HAL_UART_Receive_IT() with a high value for buffer_idx. Only after the callback of the first rx byte, the HAL_UART_Receive_IT() will use a buffer_idx of 0.

    Explorer II
    January 15, 2025

    Sorry, but I am not sure what the "previous reception" is. The first reception should be the byte 0xB5, so there should not be a previous reception that comes before this.

    You said that buffer_idx is initially some high value before the "previous reception" and gets set to 0 only after the callback of the first rx byte (0xB5). Why is that? I set buffer_idx to 0 before calling HAL_UART_Receive_IT().

     

    I placed a breakpoint inside my callback function, and when looking inside the RDR register i see 0x62 instead of 0xB5. The callback function is never called when the MCU receives 0xB5, so 0xB5 is never stored inside the buffer. Why does it skip over this first byte?

    Graduate II
    January 15, 2025

    You've created a race condition by the arbitary output of query message, delays, then setting the input buffer index to zero.

    Try NOT doing that, and instead get all the data and THEN try synchronizing the frame pattern (0xB5,0x62) or do the synchronization in the handler.

    Don't observe the UART registers in the debugger, it will have side effects of reading the DR/RDR, and changing bits in the SR/ISR

    Range check the scope of the pointer/index in the handler, perhaps flag you're about to send a query and have the handler set the index to zero when it sees the 0xB5

    Use volatile variables for things that change outside normal linear code flow, ie in interrupts/call backs.

    Graduate II
    January 15, 2025

    @HamzaBeder wrote:

    MCU: STM32L476RGT6

    Hello,

    I am using UART to read data from the NEO-M9N GPS receiver. My receive buffer stores all received data besides the first byte:

    received_GPS.pngReceived_GPS2.png

    This forum states to add a delay between initializing UART and sending data, and this forum states to clear the buffer before transmitting data. However, neither solution works for me. These forums are addressing an issue where the first byte received is 0x00. However, my issue is that rather than receive 0x00, I skip the first byte entirely.

    Any tips on how to fix this would be appreciated. Thanks.

    static void MX_USART3_UART_Init(void);
    UART_HandleTypeDef huart3;
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    uint8_t buffer[100];
    uint8_t buffer_idx;

    int main(void)
    {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART3_UART_Init();
    buffer_idx=0;
    while(HAL_TIMEOUT != HAL_UART_Receive(&huart3, buffer, 1, 10));
    HAL_UART_Receive_IT(&huart3, buffer, 1);
    HAL_Delay(1);
    while (1) {
    uint8_t arr[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30};
    HAL_UART_Transmit(&huart3, arr, sizeof(arr), HAL_MAX_DELAY);
    HAL_Delay(100);
    buffer_idx=0;
    HAL_Delay(1000);
    }
    }

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    HAL_UART_Receive_IT(&huart3, buffer+buffer_idx, 1);
    buffer_idx++;
    }

     


    Maybe I'm missing something but if you're communicating with the GPS module by UART, you should be receiving strings. The data you show in the buffer isn't a readable string.

    What baud rate is the STM32 set for?

     

    Graduate II
    January 16, 2025

    u-blox GPS receiver support a proprietary binary protocol called UBX, there frames start with 0xB5 0x62 (µb).

    Explorer
    January 16, 2025

    As already explained by others, the problem is your code.

    It should have been clear by taking a closer look at the logic analyser image. The first byte - 0xB5 - is clearly present.
    When debugging, the initial assumption should always be that one's own code is the issue.