cancel
Showing results for 
Search instead for 
Did you mean: 

Having issues reading a UART string into a buffer, getting garbage data.

Dandrews
Associate II

I am attempting to read a NEMA message from a GPS over UART.

Im expecting the message to be about 75 chars/bytes long.

Heres a sample of the data I'm seeing when using an ardunio for testing the GPS data out over UART.

$GNGGA,011112.00,3214.62073,N,05800.07397,W,2,12,1.14,22.0,M,-33.2,M,,0000*45

However when I use the code below I get a ton of junk data mixed in with good data.

HAL_UART_Receive_DMA(&huart1, &rxByte, 1);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if(rxByte == 0x6e && rx_buff[rxIdx--] == 0x5c || rxIdx >= 73) {
        rx_buff[rxIdx] = rxByte;
        sprintf(statusBuf, "%s", rx_buff);
        CDC_Transmit_FS((uint8_t *) statusBuf, strlen(statusBuf));
        memset(statusBuf, 0, 128);
        rxFlag = 1;
        rxIdx = 0;
    }
    else {
        rx_buff[rxIdx] = rxByte;
        rxIdx++;
    }
    HAL_UART_Receive_DMA(&huart1, &rxByte, 1);
}

Example of the junk data being printed out

µb\ÿê®Õmˆ.òâÿÿ°dZ$GNGGA,023050.00,3214.87989,N,05800.08063,W,2,12,1.03,25.8,M,-3          0*49
µb\W,2,12,1.03,25.8,M,-33.2,M,,0000*4C
µb\œâÿÿ[d52.00,3214.87990,N,05800.08064,W,2,12,1.03,25.7,M,-33.2,M,,0000*         ˜}ýå57%¦25.6,M,-33.2,M,,0000*47
µb\7993,N,05800.08056,W,2,12,0.98,25.4,M,-33.2,M,,0000*4F
µb\%,M,,0000*47
µb\.08061,W,2,12,0.98,25.3,M,-33.2,M,,0000*48
µb\®Õzˆ.“àÿÿQbGA,023057.00,3214.87996,N,05800.08062,W,2,12,0.98,25.2,M,-33.2,M          
µb\2,1.38,25.1,M,-33.2,M,,0000*4A
µb\Âa,3214.87994,N,05800.08062,W,2,12,1.32,25.0,M,-33.2,M,,0000*47
µ    M,-33.2,M,,0000*46

Ideally I would like to read into the buffer until I see a \r\n and have a clean string I could split and parse.

I've tried using UART_IT, with a similar buffer method and ran into similar issues. Same with polling. However the data is clean and works great with other micros.

Im using an stm32f303c8t6.

1 ACCEPTED SOLUTION

Accepted Solutions

Should probably make sure rx_buff is properly NUL terminated before using string functions on it.

Also,you should resync the line at the '$', as you look to be getting uBlox UBX packets intermixed with your NMEA sentences.

rxByte >= 73 ?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

6 REPLIES 6
TDK
Guru

CDC_Transmit_FS doesn't always succeed. You need to ensure the USB is free.

CDC_Transmit_FS works in the background. You need to ensure the buffer is valid for as long as it takes. In your code, you immediately clear it.

A better method would be to set up a circular buffer and pop chars out of it as they come in via polling in the main loop. This method requires the micro to process a char and call HAL_UART_Receive_DMA before the start of the next character, which may not always happen.

If you feel a post has answered your question, please click "Accept as Solution".

Should probably make sure rx_buff is properly NUL terminated before using string functions on it.

Also,you should resync the line at the '$', as you look to be getting uBlox UBX packets intermixed with your NMEA sentences.

rxByte >= 73 ?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Good to know about CDC_Transmit_FS. I was unaware it was back-grounded, and thought I was clearing it after it had been sent off.

I'll give the circular buffer idea a try and see if I can not get more consistent data. Thanks!

I have the rx_buff being set with a memset before my apps main while loop. And the rxByte >= 73 was a copy/paste mistake. I've edited that to have my current check for 5c 6e, or \n. The index >=73 was from an observation made on my known good data, every msg was exactly 73 chars. Tho I do know that will change some depending on message content.

Given the line lengths change the input code should put the NUL terminations on before sprintf() ing it.

Better yet just dispense with the sprintf(), and copy the buffer whose length you already know.

The receiver isn't sending the \r\n characters literally, it is sending them as 0x0D and 0x0A bytes, like $ is 0x24

0693W00000DqI9RQAV.jpg

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

So this was super helpful, I did have UBX packets being sent, and that was causing all kinds of problems as I was building under the assumption that I only had the one message type enabled.

I cracked open the interface manual that goes with this chip and I think it is actually sending \r\n literally. 0693W00000DqIcYQAV.png 

Also I figured the message length could change, and turns out it can vary a little. So instead of looking for the $ and getting the next N bytes. I made the buffer larger than max message length. I look for the $ byte, and know I now have the previous msg in buffer, process it, clear buffer, stick $ back at the front.

And that now all works perfectly. Thank you for all the help!