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字节)
  • 还有别的吗
这里有一个陷阱:CRC4的建议消息长度为11位,这里计算为12位

不,这里计算的是16位

据我所知,这意味着CRC错误检测性能会降低(但我不确定会降低多少)

关于CRC的建议可能涉及到您是否有100%的机会发现单个位错误。所有CRC都会遇到多位错误,不一定能找到它们

在处理UART的CRC可靠性计算时,还必须考虑开始位和停止位。在这种情况下,硬件可能会也可能不会帮助查找错误

一条消息的第二个字节和下一条消息的第一个字节有时构成正确的消息

当然。你没有同步机制,你期待什么?这与CRC无关

我的问题是-有没有任何方法可以在不增加任何字节的情况下纠正帧

您必须牺牲每字节一位作为同步标志,或者增加数据包长度。或者,您可以在数据位之间使用不同的延迟。可能会在两个字节之后直接发送,然后使用延迟

选择哪种方法取决于数据的性质和您的规范。没有人能告诉你你的规格是什么样子的

也许还有其他一些错误检测方法比CRC4更有效

不太可能。CRC几乎是唯一的专业校验和算法。多项式是根据噪声的例外性质选择的——它们选择的多项式尽可能少地提醒噪声。然而,这主要是学术上的兴趣,因为没有CRC专家知道噪声在您的特定应用中是什么样子的

可供选择的有求和、异或、奇偶校验、1的计数等。。。从概率上看,它们都很糟糕

如果我们必须附加更多字节,那么最好的方法是什么

如果不知道数据的性质,没有人能回答这个问题

这里有一个陷阱:CRC4的建议消息长度为11位,这里计算为12位

不,这里计算的是16位

据我所知,这意味着CRC错误检测性能会降低(但我不确定会降低多少)

关于CRC的建议可能涉及到您是否有100%的机会发现单个位错误。所有CRC都会遇到多位错误,不一定能找到它们

在处理UART的CRC可靠性计算时,还必须考虑开始位和停止位。在这种情况下,硬件可能会也可能不会帮助查找错误

一条消息的第二个字节和下一条消息的第一个字节有时构成正确的消息

当然。你没有同步机制,你期待什么?这与CRC无关

我的问题是-有没有任何方法可以在不增加任何字节的情况下纠正帧

您必须牺牲每字节一位作为同步标志,或者增加数据包长度。或者,您可以在数据位之间使用不同的延迟。可能会在两个字节之后直接发送,然后使用延迟

选择哪种方法取决于数据的性质和您的规范。没有人能告诉你你的规格是什么样子的

也许还有其他一些错误检测方法比CRC4更有效

不太可能。CRC几乎是唯一的专业校验和算法。多项式是根据噪声的例外性质选择的——它们选择的多项式尽可能少地提醒噪声。然而,这主要是学术上的兴趣,因为没有CRC专家知道噪声在您的特定应用中是什么样子的

可供选择的有求和、异或、奇偶校验、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;
        }
    } 
}