先提供一些资料,本文使用的是CRC-16、CRC-CCITT或是任何自定义的CRC-16生成多项式
标准CRC生成多项式 | |||
名称 | 生成多项式 | 简记式 | 标准引用 |
CRC-4 | x4+x+1 | 0x3 | ITU G.704 |
CRC-8 | x8+x5+x4+1 | 0x31 | |
CRC-8 | x8+x2+x1+1 | 0x07 | |
CRC-8 | x8+x6+x4+x3+x2+x1 | 0x5E | |
CRC-12 | x12+x11+x3+x+1 | 80F | |
CRC-16 | x16+x15+x2+1 | 0x8005 | IBM SDLC |
CRC16-CCITT | x16+x12+x5+1 | 0x1021 | ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS |
CRC-32 | x32+x26+x23+...+x2+x+1 | 0x04C11DB7 | ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS |
CRC-32c | x32+x28+x27+...+x8+x6+1 | 0x1EDC6F41 | SCTP |
先看一个CRC-16校验的例子了解CRC校验码是怎样生成的,待校验数据0xa743,此处使用的简记式为CRC-16 0x8005
以下就是我写的代码和流程图,代码在VC6.0环境下测试通过,不过由于scanf("%x",B)经过测试最多只能存4字节16进制数,所以,只有在N<=4的情况下正常,此问题正在寻找解决方案中。
#include#define N 4 #define U16_MSB(x) ((x)&0x8000) #define GEN_P 0x1021 //CRC-CCITT简记式,简记式中忽略最高位1,可换为CRC-16简记式0x8005或任意自定义简记式 #define MASK(x) (1<<(x)) typedef unsigned char uint8; typedef unsigned short uint16; main() { uint8 B[N]; uint8 i,j,cnt,temp_msb; uint16 temp; while(1) { cnt=0; scanf("%x",B); //经测试,%x对应只能存32bit数据,小端存储,“高高低低” temp=B[N-1]; temp=temp<<8; temp+=B[N-2]; while(1) { if(cnt==N*8) break; temp_msb=!!U16_MSB(temp); //取两次反转化为布尔类型 i=cnt%8; j=cnt/8; temp=temp<<1; cnt++; if((N-2-1-j)>=0 && B[N-2-1-j] & MASK(8-1-i)) temp++; if(temp_msb) temp^=GEN_P; } printf("CRC:%#x\n",temp); } }
要验证之前的例子,先将代码做一些修改,由于在编程之前就想到要适应不同的数据位数和生成多项式,这里的修改就很容易,只需修改宏定义,如下
#define N 2 #define GEN_P 0x8005
结果:
结果与之前分析的表格相符 此处高字节在前低字节在后
不过CRC应该是高字节在后低字节在前,这应该是很好改的。