11

我正在尝试将 CRC16 错误检测添加到摩托罗拉 HCS08 微控制器应用程序中。不过,我的校验和不匹配。一个在线 CRC 计算器既提供了我在 PC 程序中看到的结果,也提供了我在微电脑上看到的结果。

它将 micro 的结果称为“XModem”,将 PC 的结果称为“Kermit”。

这两个古老的协议指定使用 CRC16 的方式有什么区别?

4

3 回答 3

29

您可以使用相同的基本代码库实现 16 位 IBM、CCITT、XModem、Kermit 和 CCITT 1D0F。请参阅http://www.acooke.org/cute/16bitCRCAl0.html,它使用来自http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code的代码

下表显示了它们的不同之处:

name    polynomial  initial val  reverse byte?  reverse result?  swap result?
CCITT         1021         ffff             no               no            no
XModem        1021         0000             no               no            no
Kermit        1021         0000            yes              yes           yes
CCITT 1D0F    1021         1d0f             no               no            no
IBM           8005         0000            yes              yes            no

其中“反转字节”表示每个字节在处理之前进行位反转;'reverse result'表示16位结果在处理后进行位反转;'swap result' 表示结果中的两个字节在处理后被交换。

以上所有内容都通过针对http://www.lammertbies.nl/comm/info/crc-calculation.html的测试向量进行了验证(如果这是错误的,我们都迷失了......)。

因此,在您的特定情况下,您可以通过位反转每个字节,位反转最终结果,然后交换结果中的两个字节,将 XModem 的代码转换为 Kermit。

[我相信,但尚未检查或计算出细节,反转每个字节相当于反转多项式(加上一些额外的细节)。这就是为什么对于基本相同的算法,您会在不同的地方看到截然不同的解释。

此外,上述方法效率不高,但适合测试。如果您想要高效,最好的办法是将上述内容转换为查找表。]

编辑我上面所说的 CCITT 在RevEng 目录中记录为 CCITT-FALSE。有关更多信息,请参阅上面链接中对我的博客文章的更新。

于 2013-08-04T19:03:51.040 回答
4

我的回忆(我过去曾经做过调制解调器的事情)是 Kermit 首先使用最低有效位来处理数据的每个字节中的位。

大多数软件 CRC 实现(可能是 Xmodem)首先运行数据字节的最高有效位。

查看用于链接到的 CRC 计算页面的库源(从http://www.lammertbies.nl/comm/software/index.html下载)时,您会看到 XModem 使用 CRC16-CCITT,多项式为:

x^16 + x^12 + x^5 + 1  /* the '^' character here represents exponentition, not xor */

多项式由位图表示(注意位 16 是隐含的)

0x1021 == 0001 0000 0010 0001  binary

Kermit 实现使用:

0x8408 == 1000 0100 0000 1000  binary

这与 XModem 的位图相同,只是颠倒了。

库附带的文本文件还提到了 Kermit 的以下区别:

仅适用于 CRC-Kermit 和 CRC-SICK:在所有输入处理之后,计算 CRC 的补码并交换 CRC 的两个字节。

因此,修改您的 CRC 例程以匹配 PC 结果可能应该很容易。请注意,CRC 库中的源代码似乎有一个非常自由的许可证 - 或多或少地使用它可能是有意义的(至少适用于您的应用程序的部分)。

于 2010-12-15T21:59:37.560 回答
0

X-调制解调器 1K CRC16。

使用输入数据 {0x01, 0x02} 和多项式 0x1021 处理字节方式 CRC-16

  1. 初始化 crc = 0
  2. 处理第一个输入字节 0x01: 2.1 'Xor-in' 第一个输入字节 0x01 到 crc 的 MSB(!): 0000 0000 0000 0000 (crc) 0000 0001 0000 0000 (输入字节 0x01 左移 8)


    0000 0001 0000 0000 = 0x0100 这个结果的 MSB 是我们的电流除数:MSB(0x100) = 0x01。2.2 所以 0x01 是除数。从我们的表中获取除数的余数:crctable16[0x01] = 0x1021。(这个值是上面手动计算的 famila。)记住当前的 crc 值是 0x0000。移出当前 crc 的 MSB 并与当前余数异或得到新的 CRC: 0001 0000 0010 0001 (0x1021) 0000 0000 0000 0000 (CRC 0x0000 左移 8 = 0x0000)


    0001 0000 0010 0001 = 0x1021 = 中间CRC。

  3. 处理下一个输入字节 0x02:目前我们有中间 crc = 0x1021 = 0001 0000 0010 0001。3.1 'Xor-in' 输入字节 0x02 到 crc 的 MSB(!): 0001 0000 0010 0001 (crc 0x1021) 0000 0010 0000 000字节 0x02 左移 8)


    0001 0010 0010 0001 = 0x1221 这个结果的 MSB 是我们的电流除数:MSB(0x1221) = 0x12。3.2 所以 0x12 是除数。从我们的表中获取除数的余数:crctable16[0x12] = 0x3273。记住当前的 crc 值为 0x1021。移出当前 crc 的 MSB 并与当前余数异或得到新的 CRC: 0011 0010 0111 0011 (0x3273) 0010 0001 0000 0000 (CRC 0x1021 左移 8 = 0x2100)


    0001 0011 0111 0011 = 0x1373 = 最终CRC。

于 2018-08-06T21:35:58.540 回答