我正在尝试将CRC16错误检测添加到Motorola HCS08微控制器应用程序中。不过,我的校验和不匹配。一 在线CRC计算器 既提供我在PC程序中看到的结果,又提供我在Micro上看到的结果。

它称Micro的结果为“ Xmodem”和PC的结果为“ kermit”。

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

有帮助吗?

解决方案

您可以使用相同的基本代码库来实现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

“反向字节”表示每个字节在处理之前都对其进行了反向; “反向结果”意味着16位结果在处理后会被转换。 “交换结果”意味着结果中的两个字节在处理后被交换。

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

因此,在您的特殊情况下,您可以通过对每个字节进行逆转,对最终结果进行逆转,然后在结果中交换两个字节来将Xmodem的代码转换为kermit。

我相信,但尚未检查或弄清楚细节,逆转每个字节等同于逆转多项式(加上一些额外的详细信息)。这就是为什么您会在不同位置看到基本相同算法的不同解释的原因。

同样,上面的方法不是有效的,但对测试很有益。如果您想有效的话,最好的办法就是将上述内容转换为查找表。

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

其他提示

我的回忆(我曾经做过调制解调器的事情,何时)是kermit首先使用最不重要的位处理数据的每个字节中的位。

大多数软件CRC实现(可能是Xmodem)首先通过数据字节来运行。

查看库来源时(从 http://www.lammertbies.nl/comm/software/index.html)用于您链接到的CRC计算页面,您会看到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库中的来源似乎具有相当自由的许可证 - 或多或少地使用它可能是有意义的(至少适用于您的应用程序的部分)。

X-MODEM 1K CRC16。

使用输入数据{0x01、0x02}和多项式0x1021的字节CRC-16的过程

  1. init crc = 0
  2. 处理第一个输入字节0x01:2.1'XOR-IN'首先输入字节0x01纳入CRC的MSB(!):0000 0000 0000 0000 0000(CRC)0000 0001 0000 0000 0000(输入字节0x01左移8)


    0000 0001 0000 0000 = 0x0100此结果的MSB是我们当前的部门:MSB(0x100)= 0x01。 2.2 So 0x01是分区。从我们的表格中获取剩余的差异:crctable16 [0x01] = 0x1021。 (嗯,这个值是从上面的手动计算中进行的。)请记住,当前的CRC值为0x0000。移出当前CRC的MSB并使用当前剩余的XOR,以获取新的CRC:0001 0000 0010 0001(0x1021)0000 0000 0000 0000 0000(CRC 0x0000由8 = 0x0000左移)


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

  3. Handle next input byte 0x02: Currently we have intermediate crc = 0x1021 = 0001 0000 0010 0001. 3.1 'Xor-in' input byte 0x02 into MSB(!) of crc: 0001 0000 0010 0001 (crc 0x1021) 0000 0010 0000 0000 (input字节0x02左移8)


    0001 0010 0010 0001 = 0x1221此结果的MSB是我们当前的分裂:MSB(0x1221)= 0x12。 3.2 SO 0x12是分裂的。从我们的桌子上获取剩余的差异:crctable16 [0x12] = 0x3273。请记住当前的CRC值为0x1021。移出当前CRC的MSB并与当前剩余的XOR移动以获取新的CRC:0011 0010 0111 0011(0x3273)0010 0001 0000 0000 0000(CRC 0x1021左移8 = 0x2100)


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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top