1、1CRC 理解CRC 是 Cyclic Redundancy Codes 的简写,即循环冗余码,使用 CRC 进行校验的方法称为循环冗余校验。从信道编码的理论上来说,CRC 属于线形分组码中的循环码。 是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。生成 CRC 码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为0和1取值的多项式一一对应。例如:代码 1010111 对应的多项式为 x6+x4+x2+x+1,而多项式为 x5+x3+x2+x+1 对应的代码 101111。CRC 码集选择的原则:若设码字长度为 N,信息字段为 K 位,校验字段
2、为 R 位 (N=K+R),则对于 CRC 码集中的任一码字,存在且仅存在一个 R 次多项式 g(x),使V(x)=A(x)g(x)=xRm(x)+r(x);其中: m(x)为 K 次信息多项式, r(x)为 R-1 次校验多项式,g(x)称为生成多项式:g(x)=g0+g1x+ g2x2+.+g(R-1)x(R-1)+gRxR发送方通过指定的 g(x)产生 CRC 码字,接收方则通过该 g(x)来验证收到的 CRC 码字。可以使用线形方程组描述码的规律性的分组码称为线形分组码。在传送 n-r=k 个信息元后面附加传送 r 个监督元,使得长度为 n 的码字中 r 个监督元可以使用 r 个线形无
3、关方程求出。例如(7,3)1 分组码,设该码的码字为A= a6.a5.a4.a3.a2.a1.a0,其中前 3 位是信息元,后 4 位是监督元,可以使用下面的线性方程组公式来生成 4 个监督元,显然该方程组线性无关。a3=a6+a4a2=a6+a5a1=a5+a4a0=a6+a5+a4公式 中, 为监督元;“+”运算符为模二加,满足以下 0123 , aaaa 公式 ,模二加运算与模 2 减运算结果一样,与异或运算结果一样CRC 校验码软件生成方法:借助于多项式除法,其余数为校验字段。例如:信息字段代码为: 1011001;对应 m(x)=x6+x4+x3+1 假设生成多项式为:g(x)=x4
4、+x3+1;则对应 g(x)的代码为: 11001x 4m(x)=x10+x8+x7+x4 对应的代码记为:10110010000;采用多项式除法: 得余数为: 1010 (即校验字段为:1010)发送方:发出的传输字段为: 1 0 1 1 0 0 1 1010信息字段 校验字段接收方:使用相同的生成码进行校验:接收到的字段 /生成码(二进制除法)2如果能够除尽,则正确,给出余数(1010)的计算步骤:除法没有数学上的含义,而是采用计算机的模二除法,即,除数和被除数做异或运算。进行异或运算时除数和被除数最高位对齐,按位异或。CRC 三种校验方式,C 语言的实验程序为:#include / 注意
5、:因最高位一定为“1” ,故略去const unsigned short nCRC_16 = 0x8005;/ CRC-16 = X16 + X15 + X2 + X0const unsigned short nCRC_CCITT = 0x1021;/ CRC-CCITT = X16 + X12 + X5 + X0,据说这个 16 位 CRC 多项式比上一个要好const unsigned long nCRC_32 = 0x04C11DB7;/ CRC-32 = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 +
6、 X1 + X0unsigned long Table_CRC256; / CRC 表/ 构造 16 位 CRC 表void BuildTable16( unsigned short aPoly )unsigned short i, j;unsigned short nData;unsigned short nAccum;for ( i = 0; i 8 ) *aData+;return nAccum;/ 构造 32 位 CRC 表void BuildTable32( unsigned long aPoly )unsigned long i, j;unsigned long nData;uns
7、igned long nAccum;for ( i = 0; i 24 ) *aData+;return nAccum;void main()unsigned char data100;unsigned long len(unsigned char *);printf(“Input Data:“);scanf(“%s“,data);BuildTable16( nCRC_16 );printf(“CRC-16:%xn“,CRC_16(data,len(data);BuildTable16( nCRC_CCITT );printf(“CRC_CCITT:%xn“,CRC_16(data,len(data);BuildTable32( nCRC_32 );printf(“CRC_32:%xn“,CRC_32(data,len(data);unsigned long len(unsigned char *str)unsigned long len=0;while(*str+!=0)len+;return len;该程序运行结果为:52010-11-12