计算CRC16校验和的函数

我正在开发一个库,通过RS232或RS485连接提供简单可靠的通信。 部分代码涉及对数据使用CRC16校验和来检测线路噪声的损坏。 我创build了一个函数来计算CRC16校验和,但似乎并没有输出正确的值。

我写的相关代码可以在这里find。

我正在检查我的输出对这个在线CRC计算器 。

我得出结论,要么我对如何计算CRC16的理解是错误的,要么是在线计算器是错误的(前者似乎更可能)。 有人可以告诉我哪里可能会出错吗?

有几个细节需要与特定的CRC实现“匹配” – 即使使用相同的多项式,也可能会有不同的结果,这是因为数据位处理方式的细微差异,使用CRC的特定初始值(有时是零,有时为0xffff),和/或反转CRC的位。 例如,有时一个实现可以从数据字节的低位开始工作,而有时他们将从高位开始工作(如您现在所做的那样)。

而且,在运行所有数据位后,您需要“推出”CRC的最后一位。

请记住,CRCalgorithm是devise用硬件来实现的,所以从软件的angular度来看,一些位sorting的处理方式可能并不那么有意义。

如果要按照lammertbies.nl CRC计算器页面上显示的多项式0x8005匹配CRC16,则需要对CRCfunction进行以下更改:

  • a)通过CRC循环从最低有效位而不是从最高有效位开始运行数据位
  • b)在完成input数据后,将CRC的最后16位推出CRC寄存器
  • c)反转CRC位(我猜这个位是硬件执行的结果)

所以,你的function可能如下所示:

#define CRC16 0x8005 uint16_t gen_crc16(const uint8_t *data, uint16_t size) { uint16_t out = 0; int bits_read = 0, bit_flag; /* Sanity check: */ if(data == NULL) return 0; while(size > 0) { bit_flag = out >> 15; /* Get next bit: */ out <<= 1; out |= (*data >> bits_read) & 1; // item a) work from the least significant bits /* Increment bit counter: */ bits_read++; if(bits_read > 7) { bits_read = 0; data++; size--; } /* Cycle check: */ if(bit_flag) out ^= CRC16; } // item b) "push out" the last 16 bits int i; for (i = 0; i < 16; ++i) { bit_flag = out >> 15; out <<= 1; if(bit_flag) out ^= CRC16; } // item c) reverse the bits uint16_t crc = 0; i = 0x8000; int j = 0x0001; for (; i != 0; i >>=1, j <<= 1) { if (i & out) crc |= j; } return crc; } 

当我传入"123456789"时,该函数为我返回0xbb3d

下面是计算crc16 CCITT的工作代码。 我testing了它,结果与http://www.lammertbies.nl/comm/info/crc-calculation.html提供的结果相匹配。;

 unsigned short crc16(const unsigned char* data_p, unsigned char length){ unsigned char x; unsigned short crc = 0xFFFF; while (length--){ x = crc >> 8 ^ *data_p++; x ^= x>>4; crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x); } return crc; } 

有几种不同的CRC-16品种。 看维基页面 。

每个人都会从相同的input中返回不同的结果。

所以你必须仔细select正确的一个为你的程序。

 for (pos = 0; pos < len; pos++) { crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc for (i = 8; i != 0; i--) { // Loop over each bit if ((crc & 0x0001) != 0) { // If the LSB is set crc >>= 1; // Shift right and XOR 0xA001 crc ^= CRC16; } else { // Else LSB is not set crc >>= 1; // Just shift right } } } return crc; 

我使用了以下代码示例: http : //www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5

而且这个实用程序来validation: http : //www.sunshine2k.de/coding/javascript/crc/crc_js.html