【问题标题】:How to determine CRC16 initial checksum so resulting checksum is zero如何确定 CRC16 初始校验和,因此生成的校验和为零
【发布时间】:2020-04-27 01:57:50
【问题描述】:

在 SAMD MCU 阵列之间的 SPI 通信总线上工作。

我有一个类似于{ 0x00, 0xFF, 0x00, 0xFF } 的传入数据包。 接收器芯片对传入的数据包执行 CRC16 检查。

由于我每次都期待完全相同的数据包,因此我希望在数据包有效时具有零 CRC 校验和,而不是在传输错误时具有零校验和。

我知道我可以在发送数据包时将计算出的 CRC16 添加到数据包的末尾,并且在接收端,CRC 校验将输出 0,但在这种情况下,不可能将 CRC16 校验和添加到数据包,因为数据包由 SPI 线上的多个发送芯片构成,每个芯片只填充整个数据包中自己的两个字节。

我需要在接收端加载一个初始 CRC 校验和,因此在检查传入数据包后,生成的 CRC 等于 0(如果数据包完整)。

答案here on SO其实是我要找的,不过是针对CRC32格式的,代码原理我也不是很懂,所以无法重写if for CRC16格式。

任何帮助将不胜感激!

问候, 尼可

【问题讨论】:

    标签: c++ embedded packet crc16 samd21


    【解决方案1】:

    解决方案只是使用基于查找表的 CRC。如果您无法将校验和(又名 Frame Check Sequence,FCS)附加到包中,请先进行查表,然后简单地将其与固定数据的预期序列进行比较.

    请注意,“CRC 16”可能意味着任何东西,有多个版本和(非)标准。最常见的一种可能是称为“CRC-16-CCITT”的一种,具有 1021h 多边形和初始值 FFFFh,但即使是这种算法,也有多种算法 - 有些是正确的,有些是错误的。您最大的挑战将是找到一个值得信赖的 CRC 算法。

    然而,我实际上认为 SAMD 专门使用硬件生成的片上 CRC-16-CCITT 用于 DMA 目的。由于这是 SPI,它应该是 DMA-able,所以也许调查一下你是否可以以某种方式使用它。

    【讨论】:

    • 是的,你是对的,我使用的 SAMD 硬件 CRC16 版本确实是多项式 0x1021 的 CRC-16-CCITT。读取 SPI 帧的 DMA 通道用于计算它。关于查找表,这就是我现在正在做的方式,知道传入数据包的所有可能状态,我有一个 LUT 来比较校验和。但是,我也收到带有附加 FCS 的“常规”数据包,因此我需要在传输之前预加载一个状态以了解预期的校验和。我想通过检查所有数据包的校验和是否为零来避免这种情况。
    • @NikoDiYana 我不确定您希望如何解决这个问题。附加或不附加 FCS 的包装是否会有不同的尺寸,或者您如何区分?
    • SPI主芯片向从芯片发送字节数请求。这就是它知道期望什么数据包的方式。在下一个事务中,从属响应。
    • @NikoDiYana 那么启用/禁用硬件 CRC 检查是一个选项吗?取决于您的期望。
    • 是的,但我仍然需要检查传入数据包的内容。如果线路上的芯片没有响应,则其在数据包中的插槽将为 0x00。我完全意识到我可以使用 LUT 或循环来做到这一点,但问题是主控器正在同时进行计算,并且可以在接收数据中断中完成对零的快速检查,而不会破坏主循环。跨度>
    【解决方案2】:

    感谢 Bastian Molkenthin 的建议,我找到了解决方案,他做得很好online CRC calculator

    他建议尝试对 CRC16 初始值的所有 2^16 值进行蛮力计算。实际上,在几行代码和几微秒后,SAMD51 找到了一个初始值,该值与给定缓冲区的零 CRC 值匹配。

    【讨论】:

      猜你喜欢
      • 2021-08-12
      • 2012-05-20
      • 1970-01-01
      • 2016-02-04
      • 2016-05-31
      • 1970-01-01
      • 2011-02-08
      • 2016-03-13
      • 2020-07-02
      相关资源
      最近更新 更多