2025-01-15 08:00 AM
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:
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++;
}
2025-01-15 08:26 AM
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.
2025-01-15 10:30 AM - edited 2025-01-15 10:32 AM
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?
2025-01-15 12:20 PM
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.
2025-01-15 12:31 PM
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);
}
2025-01-15 03:31 PM
@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:
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?