c语言 - 用于接收数据流的UART同步算法



我正在通过UART接收此代码$0,S1,B2,Kffffffffffff,T61*34的此帧。

//Receive Data
for(uint8_t i = 0; i < size; i++){
receivedFrame[i] = EUSART1_Read();
if(receivedFrame[i] == '*'){
size = i + 3;
}
}

帧的开头总是$的,结束总是*之后是两个字节,保存前一个字节的校验和(例如34)。

帧长度不是固定的,但它的最小长度为 26(从$*) + 2 字节的校验和和,最大长度为 62 和 + 2 字节的校验和。

但这不是最好的选择,因为可能会发生很多情况,例如,如果*没有到达,这将使我阅读的每一帧都是错误的。

我寻找通过UART接收数据的更好方法,但没有找到任何东西。 我正在寻找更好的方法来处理这样的接收帧。

此解决方案基于没有尾随 CR 或 LF 的假设,但在这种情况下,它也可以通过跳过 CR 和 LF 直到找到$来工作。

我建议将您的算法与检查$相结合,这将位置重置为 0 并将$存储在位置 0。这将忽略在预期位置不包含*的帧。

在进入循环之前,您可能应该将size初始化到最大值,并确保在收到*太晚的情况下不会增加size

此外,我会确保第一个字符是'$'的,如果这不是真的,则不会增加索引。

对于索引的这种条件递增,while循环更适合。

未经测试的提案:

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++;
}
}

附加提示:要在PC上测试算法,您可以将EUSART1_Read替换为fgetcgetchar。请注意,这些函数返回一个int值,在将其转换为unsigned char之前,应检查该值是否EOF

如果您对特殊的数据包标记感兴趣,请查找它们:等到开始($),然后记录并计算所有内容直到结束(*),然后再读取两个字符。

在记录和计数时,请检查房间以免溢出。根据预期的错误数,最好在收到"*"时重置计数,如@Bodo所建议的那样。

有没有办法知道EUSART1_Read()是否真的找到了角色?还是永远等待(危险)?最好不要等待太多,并且知道有更多的字符要阅读。

最新更新