C 非常短的串行数据包的数据包帧
我们为嵌入式设备设计了简单的定长协议。每个数据包只有两个字节:C 非常短的串行数据包的数据包帧,c,embedded,crc,serial-communication,error-detection,C,Embedded,Crc,Serial Communication,Error Detection,我们为嵌入式设备设计了简单的定长协议。每个数据包只有两个字节: bits | 15..12 | 11..4 | 3..0 | | OpCode | DATA | CRC4 | 我们使用“基于crc的帧”,即接收器收集两个字节,计算CRC4,若它与帧匹配,则视为有效。正如您所看到的,没有帧的开始或结束 这里有一个陷阱:CRC4的建议消息长度为11位,这里计算为12位。据我所知,这意味着CRC错误检测性能会降低(但我不确定会降低多少)
bits | 15..12 | 11..4 | 3..0 |
| OpCode | DATA | CRC4 |
我们使用“基于crc的帧”,即接收器收集两个字节,计算CRC4,若它与帧匹配,则视为有效。正如您所看到的,没有帧的开始或结束
这里有一个陷阱:CRC4的建议消息长度为11位,这里计算为12位。据我所知,这意味着CRC错误检测性能会降低(但我不确定会降低多少)
(顺便说一句,如果有人需要CRC4(或任何其他)的代码,但觉得自己编写代码不够熟练,boost有非常好的boost::crc函数,可以计算任何crc)
问题是:这种基于crc的成帧不起作用,我们会得到成帧错误,即一条消息的第二个字节和下一条消息的第一个字节有时会形成正确的消息
我的问题是-有没有任何方法可以在不增加任何字节的情况下纠正帧?我们花了相当长的时间压缩这两个字节中的所有内容,像这样扔掉它会有点悲伤。
不过,我们在操作码领域确实有一点空闲
- 基于时间的帧将不是很可靠,因为我们的无线信道喜欢一次“吐”几个数据包
- 也许还有其他一些错误检测方法比CRC4更有效
- 我们可以使用帧开始字节和字节填充(例如COB)(+2字节,但我不确定如何处理损坏的消息)
- 我们可以使用起始帧半字节,并将CRC扩展到CRC8(+1字节)
- 还有别的吗
如果不知道数据的性质,没有人能回答这个问题。一种常见的方法是在开始时“寻找框架”
#define GOOD_PACKETS_REQUIRED_BEFORE_SYNC 8
int state = HUNT;
int good_count = 0;
Packet GetPacket(void)
{
unsigned char fb = 0;
unsigned char sb = 0;
while (1)
{
if (state == HUNT)
{
fb = sb;
sb = GetNextByteFromUART();
if (IsValidCRC(fb, sb))
{
state = LOF;
good_count = 1;
}
}
else if (state == LOF)
{
fb = GetNextByteFromUART();
sb = GetNextByteFromUART();
if (IsValidCRC(fb, sb))
{
good_count++;
if (good_count >= GOOD_PACKETS_REQUIRED_BEFORE_SYNC)
{
state = SYNC;
}
}
else
{
state = HUNT;
good_count = 0;
}
}
else if (state == SYNC)
{
fb = GetNextByteFromUART();
sb = GetNextByteFromUART();
if (IsValidCRC(fb, sb))
{
return packet(fb, sb);;
}
// SYNC lost! Start a new hunt for correct framing
state = HUNT;
good_count = 0;
}
}
}