雨下枫的笔记 https://bbs.21ic.com/?467505 [收藏] [复制] [RSS]

日志

CRC校验

已有 1066 次阅读2011-4-5 03:14 |个人分类:技术|系统分类:通信网络| CRC

1、             什么是CRC校验


答:CRC 校验的基本思想是利用线性编码理论,在发送端根据要传送的k 位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC 码)r 位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。


2、             如何用数学表达式表达一个2进制数的数据串


答:例如现有2进制字符串:1100 1110 1011 0011


那么它对应的数学表达式为:B(X)=X^15+X^14+X^11+X^10+X^9+X^7+X^5+X^4+X^1+1,再详细点的表达如下:


B(X)=1*X^15+1*X^14+0*X^13+0*X^12+1*X^11+1*X^10+1*X^9+0*X^8+1*X^7+0*X^6+1*X^5+1*X^4+0*X^3+0*X^2+1*X^1+1*X^0


那么对于任意的二进制序列都有B(X)=Bn*2n+Bn-1*2n-1……+B1*2+B0


3、 CRC的余数项的数学表达模式如何?


答:(B(x) * 2^16) / G(x) = Q(x) + R(x)/G(x)


注:


B(X)为原始数据


R(X)为余项式,这就是我们最终想要得到的数据项


Q(X)为整数项,这个我们不关心


G(X)为多项式,这项可以自己定义,为了有通用性可以参考以下两个标准


CRC-16:(美国二进制同步系统中采用) G(X ) = X16 + X15 + X 2 +1


CRC-CCITT:(由欧洲CCITT 推荐) G(X ) = X16 + X12 + X 5 +1


4、             如何根据CRC的定义计算出余数项?


答:由于推导过程表达式用word太不好编辑了,这里就不作表述,详见附件。


注:这种计算方法也叫作按位计算,这种算法优点:节省程序空间;缺点:花费程序运行时间,在高速数据传送中不适用。


5、             如何按字节计算CRC余数项


答:由于推导过程表达式用word太不好编辑了,这里就不作表述,详见附件。


注:这种计算方法可以节省程序运行时间但花费程序空间


6、             如何用C语言按位计算CRC16余项


答:贴上自己编写的代码


/*


*********************************************************************************************************


*                                             cal_crc()


*


* Deion : 按位计算CRC,取多项式0x1021


*


* Parameters  : ptr:数据指针


*               len:数据长度


*


* Return      :


*********************************************************************************************************


*/


#ifdef __BIT_CRC16


unsigned int cal_crc(unsigned char *ptr, unsigned char len)


{


    unsigned char i;


    unsigned int crc = 0;


   


    while(len--)


    {


        for(i = 0x80; i != 0; i /= 2)


        {


            if((crc & 0x8000) != 0)


            {


                crc *= 2;


                crc ^= 0x1021;


            } /* 余式CRC 乘以2 再求CRC */


            else


            {


                crc *= 2;


            }


            if((*ptr & i) != 0)


            {


                crc ^= 0x1021; /* 再加上本位的CRC */


            }


        }


        ptr++;


    }


    return(crc);


}


#endif


7、             如何用C语言按字节计算CRC16余项


答:贴上自己编写的代码


/*


*********************************************************************************************************


*                                             ()


*


* Deion :


*


* Parameters  :


*


* Return      :


*********************************************************************************************************


*/


#ifdef __BYTE_CRC16


unsigned int cal_crc(unsigned char *ptr, unsigned char len)


{


    unsigned int crc = 0;


    unsigned char crc_high, crc_low;


   


    while(len--)


    {


        crc_high = crc >> 8;


        crc_low <<= 8;


        crc = crc16_table[*ptr ^ crc_high];


        crc ^= crc_low;


    }


}


#endif


细心的朋友会发现,按字节计算还缺一个CRC16余项的表。以下就是按多项式0x1021生成的CRC16


//多项式为0x1021


const unsigned int crc16_table[]=


{


    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,


    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,


    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,


    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,


    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,


    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,


    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,


    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,


    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,


    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,


    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,


    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,


    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,


    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,


    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,


    0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,


    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,


    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,


    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,


    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,


    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,


    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,


    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,


    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,


    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,


    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,


    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,


    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,


    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,


    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,


    0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,


    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0,


};


到此关于CRC16的余项计算原理,具体C代码的实现都已完成。如果真正理解的朋友不妨可以试着用别的多项式作一个CRC16余项表。


下一课再讲解一下如何制作CRC16余项表。


 

crc算法.pdf

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)