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.
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
.