cancel
Showing results for 
Search instead for 
Did you mean: 

How to find number of chars/bytes to read over UART channel?

TH.16.336
Associate III

Hello all,

I am using NUCLEO-F446RE board.

I am looking for some way to find how many bytes of data is received over UART which we want to read using HAL_UART_Read API.

Normally, we will know what is the incoming data. So, depending on that we Read those many bytes of data.

But in a special scenario, I don't how many bytes of data is coming. Once data is received I need to validate it. For this, I need a way to find how many bytes are coming over UART?

Please help me out.

6 REPLIES 6

Receive/check bytes one by one.

JW

Exactly.

> Normally, we will know what is the incoming data.

No, you don't.

Characters get lost or get corrupted, you can even get false receptions.

You only know how much characters you expect.

> But in a special scenario, I don't how many bytes of data is coming. Once data is received I need to validate it.

Use a protocol with designated start or end character, or better both.

Synchronize your reception on those characters.

Always assume that start/end character can get lost or corrupted as well.

Validate once you successfully received a package.

Yes True.

I can read/check byte by bytes on each interrupt. And I can just save those bytes to some array. But on what condition again, I need to reset the index of array? so that I can save the next set of data/bytes starting from 0th index? Because I don't have fixed last byte?

suppose, I want to send 0x53 0x54 0x55 ==>array should be Arr[]={0x53, 0x54, 0x55} and again 0x73 0x74 0x75 ==> array should be Arr[]={0x73, 0x74, 0x75}

> But on what condition again, I need to reset the index of array? so that I can save the next set of data/bytes starting from 0th index? Because I don't have fixed last byte?

That would be sub-optimal conditions.

You could either use the start character of the next package to conclude the preceding one. But that would imply follow-up packets, and lag in processing/response time.

Modbus RTU uses a time-based approach. An idle time of more then 3,5 character is interpreted as packet termination.

If the inherent error susceptibility of UART transmission is a problem, and you can't ensure robustness by protocoll, I would suggest to switch to something more safe like CAN. It has automatic error repetition, arbitration, error handling, and an inherent 16-bit CRC.

One (imho bad) approach: When you know a message is complete (and processed) then you reset the index. This has problems - consider what happens if you start receiving a new message before you've processed the old one?

Another approach is a circular buffer. You reset the index when you've got to the end of the buffer. Reading out is harder because you need to do a "read from here", and be aware that your reading will have to wrap back to the start sooner or later. There is hardware DMA support for this.

I tend to use circular buffers with DMA. And then copy out when I want to process the data.

Hope this helps,

Danish

KnarfB
Principal III

> But in a special scenario, I don't how many bytes of data is coming.

There is a UART idle time interrupt feature. The interrupt will trigger after the serial line was idle for a certain time. This interrupt is not covered by HAL UART API, but there is a nice article about it here: https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx