cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART does not receive first byte

HamzaBeder
Associate II

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++;
}

 

5 REPLIES 5
nicolas
Senior

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.

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?

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
static void MX_USART3_UART_Init(void);
UART_HandleTypeDef huart3;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
volatile uint8_t input;
volatile uint8_t buffer[100]; // packets can run several hundred bytes
volatile int buffer_idx = 0; // be an int, speedwise it's cheaper and can handle >255
volatile int expect_packet = 0;

int main(void)
{
 HAL_Init();
 SystemClock_Config();
 MX_GPIO_Init();
 MX_USART3_UART_Init();
 buffer_idx=0;
 while(HAL_TIMEOUT != HAL_UART_Receive(&huart3, &input, 1, 10)); // clear pending errors, but expect input
 HAL_UART_Receive_IT(&huart3, &input, 1);
 HAL_Delay(1);
 while (1) {
  static const uint8_t arr[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x0E, 0x30}; // Query UBX-CFG-RATE
  expect_packet = 1;

  HAL_UART_Transmit(&huart3, arr, sizeof(arr), HAL_MAX_DELAY);
  HAL_Delay(100);
 
  HAL_Delay(5000);
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (expect_packet && (input == 0xB5))
  {
    buffer_idx = 0;
    expect_packet = 0;
  }
  buffer[buffer_idx++] = input;
  if (buffer_idx >= sizeof(buffer)) buffer_idx = 0;
  HAL_UART_Receive_IT(&huart3, &input, 1);
}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Lead III

@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?

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.