2024年4月27日发(作者:)

最近在搞CRC校验,用的是CRC16标准,查看了很多资料发现很多讲的都是CRC16-CCITT标准,一直想弄明白CRC-16标准中的采

用查表法的方式中那两个表格中的数是如何求出来的。可惜没有一个文章仔细的讲,更没有文章给出实例来算一算。

一切只能靠自己了,谁让我喜欢寻根摸底呢。研究了一下本站会员玉丫子的文章,自己琢磨了琢磨,终于知道是怎么算出来的了。

CRC16算法的生成多项式x^16 + x^15 + x^2 + 1,十六进制表示为0x8005。

CRC16常见的表格中的数据是按照先传输LSB,消息右移进寄存器来计算的。因此需要判断寄存器的最低位LSB,同时要将0x8005

按位颠倒后(0xA001)根据LSB的情况决定是否与寄存器异或即可。

CRC16的表格中对应的数依次为0~255计算出来的CRC值,因此,此处只选取其中一两个数作为实例计算CRC值。

具体步骤如下所示:

1)从0~255中选取需要计算的数,将其对应的十六进制数放入一个长度为16的寄存器的低八位,高八位填充0;

2)如果寄存器的末位LSB为1,将寄存器的数值右移1位,再与0xA001位异或,否则仅将寄存器右移1位;

3)重复第2步,直到低八位全部右移出寄存器;

4)寄存器中的值则为校验码。

从0~255中挑选2(对应0x02)计算其CRC值:

0x02的CRC-16的表格计算(反向)

00000000 00000010 <- 最低位LSB = 0, 高八位填充0

00000000 000000010 右移,高位填充0,并舍弃最后一位

----------------- 第一次计算

00000000 00000001 <- LSB = 1

00000000 000000001 右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第二次

10100000 00000001 <- LSB = 1

01010000 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第三次

11110000 00000001 <- LSB = 1

01111000 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第四次

11011000 00000001 <- LSB = 1

01101100 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第五次

11001100 00000001 <- LSB = 1

01100110 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第六次

11000110 00000001 <- LSB = 1

01100011 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第七次

11000011 00000001 <- LSB = 1

01100001 100000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 一共右移了八次,得到的结果为CRC

11000001 10000001 <- CRC: 0xC1 81

从本文最后的附表中可以看出auchCRCHi[]的第三个值就是0x 81,auchCRCLo[]的第三个值就是0xC1,可见计算无误。

另一个计算实例,从0~255中挑选11(对应0x0B)计算其CRC值:

0x0B的CRC-16的表格计算(反向)

00000000 00001011 <- 最低位LSB = 1, 高八位填充0

00000000 000001011 右移,高位填充0,并舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第一次计算

10100000 00000100 <- LSB = 0

01010000 000000100 右移,舍弃最后一位

----------------- 第二次

01010000 00000010 <- LSB = 0

00101000 000000010右移,舍弃最后一位

----------------- 第三次

00101000 00000001 <- LSB = 1

00010100 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第四次

10110100 00000001 <- LSB = 1

01011010 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第五次

11111010 00000001 <- LSB = 1

01111101 000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第六次

11011101 00000001 <- LSB = 1

01101110 1000000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 第七次

11001110 10000001 <- LSB = 1

01100111 010000001右移,舍弃最后一位

^10100000 00000001 <-与0xA001异或

----------------- 一共算八次,得到的结果为CRC

11000111 01000001 <- CRC: 0xC7 41

从本文最后的附表中可以看出auchCRCHi[]的第12个值就是0x 41,auchCRCLo[]的第12个值就是0xC7,可见计算无误。

附:CRC-16的CRC数值表

const unsigned char auchCRCHi[] = {

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,

0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,

0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,

0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,

0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,