我正在尝试将CRC16错误检测添加到Motorola HCS08微控制器应用程序中。但是,我的校验和不匹配。一个online CRC calculator提供了我在PC程序中看到的结果和我在微观上看到的结果。
它调用micro的结果“XModem”和PC的结果“Kermit。”
这两个古老协议指定使用CRC16的方式有何不同?
答案 0 :(得分:23)
您可以使用相同的基本代码库实现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位结果在处理后进行位反转; 'swap result'表示结果中的两个字节在处理后交换。
所有上述内容均使用针对http://www.lammertbies.nl/comm/info/crc-calculation.html的测试向量进行验证(如果错误,我们都会丢失......)。
因此,在您的特定情况下,您可以通过对每个字节进行位反转,将位反转最终结果,然后将结果中的两个字节进行交换,将XModem的代码转换为Kermit。
[我相信,但没有检查或计算出细节,反转每个字节相当于反转多项式(加上一些额外的细节)。这就是为什么你会在不同的地方看到基本相同算法的不同解释。
另外,上述方法效率不高,但有利于测试。如果你想要有效率,最好的办法是将上面的内容翻译成查找表。]
编辑上面我称之为CCITT的内容在RevEng catalogue中记录为CCITT-FALSE。有关详细信息,请参阅上面链接中我的博客文章的更新。
答案 1 :(得分: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库中的源代码似乎具有非常宽松的许可证 - 使用它可能或多或少地使用它(至少适用于您的应用程序的部分)。
答案 2 :(得分:0)
处理第一个输入字节0x01: 2.1'Xor-in'首先输入字节0x01到crc的MSB(!)中: 0000 0000 0000 0000(CRC) 0000 0001 0000 0000(输入字节0x01左移8)
0000 0001 0000 0000 = 0x0100 此结果的最高有效位是我们的当前分频器:最高有效位(0x100)= 0x01。 2.2所以0x01是除数从表中获取除数的余数:crctable16 [0x01] = 0x1021。 (好吧,根据上面的手动计算,该值为家族)。 请记住,当前的crc值为0x0000。移出当前crc的MSB并将其与当前余数进行异或运算以得到新的CRC: 0001 0000 0010 0001(0x1021) 0000 0000 0000 0000(CRC 0x0000左移8 = 0x0000)
0001 0000 0010 0001 = 0x1021 =中间crc。
处理下一个输入字节0x02: 当前,我们有中间crc = 0x1021 = 0001 0000 0010 0001。 3.1'Xor-in'输入字节0x02到crc的MSB(!)中: 0001 0000 0010 0001(CRC 0x1021) 0000 0010 0000 0000(输入字节0x02左移8)
0001 0010 0010 0001 = 0x1221 该结果的最高有效位是我们的当前分频器:最高有效位(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。