CRC16-CCITT结果不正确?

时间:2017-01-26 19:17:38

标签: c crc16

我正在制作一个程序,它将与引导加载程序通信以更新微控制器的固件。除CRC calculation以外,一切准备就绪。

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

但是输入0x3304000012345678的结果出现了错误。我检查了这个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);
}

2 个答案:

答案 0 :(得分: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'循环,这样如果'length',它就不会首先进入循环是0。

4)在for循环中,data左移而不是右移。这是因为我们首先要处理其位,然后是右边的位,依此类推 - 左移位将每个后续位移动到高位位置。

5)将进位与新位输入组合在一起的if语句现在将CRC的高位(crc >> 15)与数据的高位进行比较({{1} }),而不是每个的低位。其余的代码确保data >> 7在第16位没有位,crc在第8位不会有位,所以这些位移保证产生一位仅

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

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

8)删除后处理代码。最后的uint16_t值将在循环完成时返回。

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

答案 1 :(得分:1)

CRC-16不是唯一的规范,它取决于初始化器和多项式。我怀疑0xFFFF 您使用的网站使用0x0000作为初始化程序。

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