I am receiving this frame $0,S1,B2,Kffffffffffff,T61*34
through UART with this code.
//Receive Data
for(uint8_t i = 0; i < size; i ){
receivedFrame[i] = EUSART1_Read();
if(receivedFrame[i] == '*'){
size = i 3;
}
}
The start of the frame is always $
and the end is always *
after that comes two bytes holds the check sum for the previous bytes (ex 34
).
The frame length is not fixed but it has a minimum length of 26(from $
to *
) 2 bytes of check sum and maximum length of 62 and also 2 bytes of check sum.
but it is not the best thing to use since so many scenarios could happen to make this unstable for example if the *
didn't arrive, this will make every frame I read is wrong.
I searched for better way to receive data through UART but didn't manage to find any thing. I am looking for better ways to deal with receiving frames like this.
CodePudding user response:
This solution is based on the assumption that there is no trailing CR or LF, but it will also work in this case by skipping CR and LF until $
is found.
I suggest to combine your algorithm with a check for $
which whould reset the position to 0 and store the $
at position 0. This will ignore frames that don't contain *
at the expected position.
You probably should initialize size
to the maximum before entering the loop and make sure that size
is not increased in case the *
is received too late.
Additionally I would make sure that the first character is '$'
and not increment the index if this is not true.
For this conditional incrementing of the index, a while
loop is better suited.
Untested proposal:
unsigned char receivedFrame[64];
uint8_t size = sizeof(receivedFrame);
uint8_t i = 0;
while(i < size)
{
unsigned char ch = EUSART1_Read();
if(ch == '$')
{
// in case i was > 0, ignore wrong frame, start from beginning
i = 0;
}
else if(receivedFrame[i] == '*'){
uint8_t new_size = i 3;
if(new_size < size)
{
size = new_size;
}
}
receivedFrame[i] = ch;
// stay at the first position if the character is not '$'
if((i > 0) || (ch == '$'))
{
i ;
}
}
Additional hint: For testing the algorithm on a PC you could replace EUSART1_Read
with fgetc
or getchar
. Note that these functions return an int
value which should be checked for EOF
before converting it to an unsigned char
.
CodePudding user response:
If you are interested in special packet markers, then look for them: wait until a start ($), then record and count everything until end (*), then read two chars more.
While recording and counting, check for room in order to not overflow. Depending of how many errors you expect, it could be a nice idea to reset the count when an "*" is received, as suggested by @Bodo.
Is there a way to know if EUSART1_Read() really found a character? Or does it wait for ever (dangerous)? Better would be to not wait too much, and knowing there are more chars to read.