我正在开发一个库,以便在RS232或RS485连接上提供简单可靠的通信。此代码的一部分涉及对数据使用CRC16校验和来检测线路噪声中的损坏。我已经创建了一个函数来计算CRC16校验和,但是它似乎没有输出正确的值。
我写的相关代码如下(也可以在here中找到)。
#include <stdint.h>
#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 >> (7 - bits_read)) & 1;
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
return out;
}我正在对照this online CRC calculator检查我的输出。
我得出的结论是,要么是我对如何计算CRC16的理解错了,要么是在线计算器错了(前者似乎更有可能)。谁能告诉我我可能会错在哪里?
发布于 2012-05-13 14:59:50
对于特定的CRC实现,有几个细节需要“匹配”-即使使用相同的多项式,也可能会有不同的结果,因为如何处理数据比特,使用CRC的特定初始值(有时是0,有时是0xffff)和/或颠倒CRC的比特。例如,有时一个实现将从数据字节的低位向上工作,而有时它们将从高位向下工作(就像您目前所做的那样)。
此外,在运行完所有数据位之后,您还需要“推出”CRC的最后一位。
请记住,CRC算法是为在硬件中实现而设计的,因此从软件的角度来看,一些位排序的处理方式可能没有太大意义。
如CRC16计算器页面所示,如果要将CRC16与多项式0x8005进行匹配,则需要对lammertbies.nl函数进行以下更改:
进位的
因此,您的函数可能如下所示:
#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。
发布于 2014-05-19 03:43:03
下面是计算crc16 CCITT的工作代码。我测试了它,结果与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;
}发布于 2012-05-13 01:10:45
CRC-16有几个不同的变种。参见wiki page。
其中每一个都将从相同的输入返回不同的结果。
所以你必须仔细地为你的程序选择一个正确的。
https://stackoverflow.com/questions/10564491
复制相似问题