目录
一、CRC16实现代码
二、CRC32编码字符表
三、CRC校验码的手动计算示例
四、CRC校验原理
五、CRC的生成多项式
参考
一、CRC16实现代码
思路:取一个字符(8bit),逐位检查该字符,如果为1,crc^crc_mul;同时,如果原本crc最高位是1,那么crc^crc_mul后左移1位,否则只是左移一位。计算完一个字符后,装入下一个字符。
#include<stdio.h> #define crc_mul 0x1021 //生成多项式 unsigned int cal_crc(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned int crc=;
while(len-- != )
{
for(i=0x80; i!=; i>>=)
{
if((crc&0x8000)!=)
{
crc<<=;
crc^=(crc_mul);
}else{
crc<<=;
}
if((*ptr&i)!=)
{
crc ^= (crc_mul);
}
}
ptr ++;
}
return (crc);
} int main()
{
unsigned char i[] = {0x00,0x00,0x00,0x00,0x06,0x0d,0xd2,0xe3};
unsigned int crc;
crc=cal_crc(i,);
return ;
}
/*结果:7123dbc0*/
其实,世界上一共就256个字符,每装载一个就运算一遍,实在是浪费CPU,不如直接把每个字符的CRC都算出来存入数组。因此,就有了CRC编码字符表。
二、CRC32编码字符表
#include<stdio.h>
unsigned int CRC32_table[] = {};
void init_CRC32_table()
{
for (int i = ; i != ; i++)
{
unsigned int CRC = i;
for (int j = ; j != ; j++)
{
if (CRC & )
CRC = (CRC >> ) ^ 0xEDB88320;
else
CRC >>= ;
}
CRC32_table[i] = CRC;
}
}
unsigned int GetCRC32(unsigned char* buf, unsigned int len)
{
unsigned int CRC32_data = 0xFFFFFFFF;
for (unsigned int i = ; i != len; ++i)
{
unsigned int t = (CRC32_data ^ buf[i]) & 0xFF;
CRC32_data = ((CRC32_data >> ) & 0xFFFFFF) ^ CRC32_table[t];
}
return ~CRC32_data;
} int main()
{
unsigned char i[] = {0x00,0x00,0x00,0x00,0x06,0x0d,0xd2,0xe3};
init_CRC32_table();
printf("BUFFER i's CRC32: 0x%x\n", GetCRC32(i,));
printf("CRC32 TABLE:\n");
for(int i=;i<;i++)
{
printf("0x%8x\t",CRC32_table[i]);
if((i+)% == )
printf("\n");
}
}
/*结果如下:
BUFFER i's CRC32: 0xc29c07b9
CRC32 TABLE:
0x 00x770730960xee0e612c0x990951ba0x 76dc4190x706af48f0xe963a5350x9e6495a3
0x edb88320x79dcb8a40xe0d5e91e0x97d2d9880x 9b64c2b0x7eb17cbd0xe7b82d070x90bf1d91
0x1db710640x6ab020f20xf3b971480x84be41de0x1adad47d0x6ddde4eb0xf4d4b5510x83d385c7
0x136c98560x646ba8c00xfd62f97a0x8a65c9ec0x14015c4f0x63066cd90xfa0f3d630x8d080df5
0x3b6e20c80x4c69105e0xd56041e40xa26771720x3c03e4d10x4b04d4470xd20d85fd0xa50ab56b
0x35b5a8fa0x42b2986c0xdbbbc9d60xacbcf9400x32d86ce30x45df5c750xdcd60dcf0xabd13d59
0x26d930ac0x51de003a0xc8d751800xbfd061160x21b4f4b50x56b3c4230xcfba95990xb8bda50f
0x2802b89e0x5f0588080xc60cd9b20xb10be9240x2f6f7c870x58684c110xc1611dab0xb6662d3d
0x76dc41900x 1db71060x98d220bc0xefd5102a0x71b185890x 6b6b51f0x9fbfe4a50xe8b8d433
0x7807c9a20x f00f9340x9609a88e0xe10e98180x7f6a0dbb0x 86d3d2d0x91646c970xe6635c01
0x6b6b51f40x1c6c61620x856530d80xf262004e0x6c0695ed0x1b01a57b0x8208f4c10xf50fc457
0x65b0d9c60x12b7e9500x8bbeb8ea0xfcb9887c0x62dd1ddf0x15da2d490x8cd37cf30xfbd44c65
0x4db261580x3ab551ce0xa3bc00740xd4bb30e20x4adfa5410x3dd895d70xa4d1c46d0xd3d6f4fb
0x4369e96a0x346ed9fc0xad6788460xda60b8d00x44042d730x33031de50xaa0a4c5f0xdd0d7cc9
0x5005713c0x270241aa0xbe0b10100xc90c20860x5768b5250x206f85b30xb966d4090xce61e49f
0x5edef90e0x29d9c9980xb0d098220xc7d7a8b40x59b33d170x2eb40d810xb7bd5c3b0xc0ba6cad
0xedb883200x9abfb3b60x 3b6e20c0x74b1d29a0xead547390x9dd277af0x 4db26150x73dc1683
0xe3630b120x94643b840x d6d6a3e0x7a6a5aa80xe40ecf0b0x9309ff9d0x a00ae270x7d079eb1
0xf00f93440x8708a3d20x1e01f2680x6906c2fe0xf762575d0x806567cb0x196c36710x6e6b06e7
0xfed41b760x89d32be00x10da7a5a0x67dd4acc0xf9b9df6f0x8ebeeff90x17b7be430x60b08ed5
0xd6d6a3e80xa1d1937e0x38d8c2c40x4fdff2520xd1bb67f10xa6bc57670x3fb506dd0x48b2364b
0xd80d2bda0xaf0a1b4c0x36034af60x41047a600xdf60efc30xa867df550x316e8eef0x4669be79
0xcb61b38c0xbc66831a0x256fd2a00x5268e2360xcc0c77950xbb0b47030x220216b90x5505262f
0xc5ba3bbe0xb2bd0b280x2bb45a920x5cb36a040xc2d7ffa70xb5d0cf310x2cd99e8b0x5bdeae1d
0x9b64c2b00xec63f2260x756aa39c0x 26d930a0x9c0906a90xeb0e363f0x720767850x 5005713
0x95bf4a820xe2b87a140x7bb12bae0x cb61b380x92d28e9b0xe5d5be0d0x7cdcefb70x bdbdf21
0x86d3d2d40xf1d4e2420x68ddb3f80x1fda836e0x81be16cd0xf6b9265b0x6fb077e10x18b74777
0x88085ae60xff0f6a700x66063bca0x11010b5c0x8f659eff0xf862ae690x616bffd30x166ccf45
0xa00ae2780xd70dd2ee0x4e0483540x3903b3c20xa76726610xd06016f70x4969474d0x3e6e77db
0xaed16a4a0xd9d65adc0x40df0b660x37d83bf00xa9bcae530xdebb9ec50x47b2cf7f0x30b5ffe9
0xbdbdf21c0xcabac28a0x53b393300x24b4a3a60xbad036050xcdd706930x54de57290x23d967bf
0xb3667a2e0xc4614ab80x5d681b020x2a6f2b940xb40bbe370xc30c8ea10x5a05df1b0x2d02ef8d
*/
三、CRC校验码的手动计算示例
生成多项式:G(X)=X+X+1,要求出二进制序列10110011的CRC校验码。
(1)G(X)=X+X+1,二进制比特串为11001;(有X的几次方,对应的2的几次方的位就是1)
(2)因为校验码4位,所以10110011后面再加4个0,得到101100110000,用“模2除法”(其实就是亦或^)即可得出结果;
图5-10 CRC校验码计算示例
(3)CRC^101100110000得到101100110100。发送到接收端;
(4)接收端收到101100110100后除以11001(以“模2除法”方式去除),余数为0则无差错;
四、CRC校验原理
在k位信息码后再拼接r位的校验码,报文编码长度为n位,因此,这种编码又叫(n,k)码。
定理:对于一个给定的(n,k)码,可以证明,存在一个最高次幂为n=k+r的多项式G(x),存在且仅存在一个R次多项式G(x),使得。
其中:
m(x) :k次信息多项式,
r(x) :r-1次校验多项式,
g(x):生成多项式:。
发送方通过指定的G(x)产生r位的CRC校验码,接收方则通过该G(x)来验证收到的报文码的CRC校验码是否为0。
假设发送信息用信息多项式C(X)表示,将C(x)左移r位,则可表示成C(x)*2,这样C(x)的右边就会空出r位校验码的位置,做除法(模2除),得到的余数R就是校验码。发送的CRC编码是,验证接收到的报文编码是否至正确,依然是做模2除:。
五、CRC的生成多项式
生成多项式的选取应满足以下条件:
a、生成多项式的最高位和最低位必须为1。
b、当被传送信息(CRC码)任何一位发生错误时,被生成多项式做模2除后,应该使余数不为0。
c、不同位发生错误时,应该使余数不同。
d、对余数继续做模2除,应使余数循环。
主要的生成多项式G(x)有以下几种:
名称 | 生成多项式 | 数值式 | 简记式 | 标准引用 |
CRC-16 | x+x+x+1 | 0x1’8005 | 8005 | IBM SDLC |
CRC-CCITT | x+x+x+1 | 0X1’1021 | 0x1021 | ISO HDLC,ITU X.25,V.34/V.41/V.42,PPP-FCS |
CRC-32 | 注* | 0X1’04C11DB7 | 0x04C11DB7 | ZIP,RAR,IEEE 802 LAN/FDDI,IEEE1394,PPP-FCS |
注* x+x+x+x+x+x+x+x+x+x+x+x+x+x+1
下表中的生成多项式G(x)也常见的:
名称 | 生成多项式 | 数值式 | 简记式 | 标准引用 |
CRC-4 | x+x+1 | 0x1’3 | 0x3 | ITU G.704 |
CRC-8 | x+x+x+1 | 0x1’31 | 0x31 | |
CRC-8 | x+x+x+1 | 0x1’07 | 0x07 | |
CRC-8 | x+x+x+x+x+x | 0x1’5E | 0x5E | |
CRC-12 | x+x+x+x+x+1 | 0x1’80F | 0x80F | |
CRC-32c | 注** | 0X1’1EDC6F41 | 0x1EDC6F41 | SCTP |
注** x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+x+1
参考:
http://blog.chinaunix.net/uid-2630593-id-2138511.html