2017-01-26 182 views
1

我正在制作一个程序,它将与引导加载程序进行通信以更新微控制器的固件。除了CRC calculation以外,一切都准备就绪。CRC16-CCITT不正确的结果?

我已经使用来自here的CRC计算函数来计算多项式为x16 + x12 + x5 + 1(0b10001000000100001)的CRC16。

但输入0x3304000的结果出来是错误的。我检查了这个website。此外,我有一个python脚本,我复制C复查。 python脚本正确计算了CRC

下面是从网站的代码:

uint16_t crc16(uint8_t *data_p, unsigned length) 
{ 
    unsigned char i; 
    unsigned int data; 
    unsigned int crc = 0xffff; 

    if (length == 0) 
     return (~crc); 

    do 
    { 
     for (i=0, data=(unsigned int)0xff & *data_p++; 
      i < 8; 
      i++, data >>= 1) 
     { 
       if ((crc & 0x0001)^(data & 0x0001)) 
        crc = (crc >> 1)^POLY; 
       else crc >>= 1; 
     } 
    } while (--length); 

    crc = ~crc; 
    data = crc; 
    crc = (crc << 8) | (data >> 8 & 0xff); 

    return (crc); 
} 
+0

我会责怪排序。 –

+0

我正在传递'uint8_t'数组。我认为endianess不应该是一个问题。 – abhiarora

+0

您如何知道网站正在使用CRC16-CCITT? –

回答

3

我比你贴与你链接的网站算法的C代码,我发现两个主要区别:

1)您发布流程以相反的顺序位的C代码的网站。对于CRC计算本身(右移,网站左移)以及处理输入的每个字节(首先处理最低有效位,网站首先处理最重要位),这都是正确的。

2)C代码在返回之前将CRC值中的所有位反转,并且还交换低位和高位字节。该网站的算法不包含这种后期处理。

我已经更新您粘贴相匹配的网站上的C代码:

uint16_t crc16(const uint8_t *data_p, unsigned length) 
{ 
    unsigned char i; 
    uint8_t data; 
    unsigned int crc = 0; // 0xffff; 

    while (length-- > 0) 
    { 
    for (i = 0, data = *data_p++; 
     i < 8; 
     i++, data <<= 1) 
    { 
     if ((crc >> 15)^(data >> 7)) 
     crc = (crc << 1)^POLY; 
     else 
     crc <<= 1; 

     crc &= 0xffff; 
    } 
    } 

    return crc; 
} 

的差异:

1)data局部变量现在uint8_t类型。

2)crc变量初始化为0而不是0xFFFF,正如@AShelly所建议的。该网站特别提到它在开始计算之前将所有寄存器初始化为0。 3)我没有单独测试长度0,而是将循环从'do'循环重新编译为'while'循环,这样它就不会首先进入循环,如果'长度'为0.

4)在for循环中,data向左移动而不是向右移动。这是因为我们想要先处理它的位,然后是位右边的位,等等 - 左边的移位将每个后续位移到高位位置。

5)if语句与输入的新的比特现在与数据(data >> 7)的高比特比较CRC(crc >> 15)的高比特结合了进位,而不是每一个的低比特。代码的其余部分确保crc在第16位没有位,并且data在第8位不会有位,所以这些位移保证只产生一位。

6)实际的crc计算向左移动而不是右移。

7)将crc向左移位后,我将位置16的任何位屏蔽掉。这是第4点中提到的代码的一部分,它确保crc >> 15只产生一个位。 (这也可以通过使crcuint16_t类型来完成。)

8)后处理代码被删除。最后的crc值将按照循环完成时的原样返回。

通过这些更改,由C函数生成的CRC与网站相匹配。

+2

很好的答案,但错过了使用“downto”运算符的机会:'while(length - > 0) – AShelly

+0

感谢您的回答。它按预期工作。我也试图匹配到该网站已实施的内容,但我想我错过了几件事情。很好的答案。值得一百万赞助人 – abhiarora

1

CRC-16并不是唯一的规范,这取决于初始化和多项式。我怀疑0xFFFF 您使用的网站使用0x0000作为初始值设定项。

在过去的工作中,我们使用this website来验证实现,首先验证了几个已知输入的网站结果。

+0

是的,我已经看过他们的算法,并试图在我的程序中使用0x0000初始值设定项,但它没有帮助 – abhiarora