|||
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,0x
0x8108,0x9129,0xa
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x
0x9339,0x8318,0xb37b,0xa
0x2462,0x3443,0x0420,0x1401,0x64e6,0x
0xa
0x3653,0x2672,0x1611,0x0630,0x76d7,0x
0xb75b,0xa
0x
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa
0x5af5,0x4ad4,0x7ab7,0x
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab
0x6ca6,0x
0xedae,0xfd
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
0xff
0x9188,0x
0x1080,0x
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd
0x02b1,0x1290,0x
0xb5ea,0xa5cb,0x
0x34e2,0x
0xa7db,0xb7fa,0x8799,0x97b8,0xe
0x26d3,0x
0xd
0x5844,0x4865,0x7806,0x6827,0x
0xcb7d,0xdb
0x
0xfd2e,0xed
0x
0xef
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0,
};
到此关于CRC16的余项计算原理,具体C代码的实现都已完成。如果真正理解的朋友不妨可以试着用别的多项式作一个CRC16余项表。
下一课再讲解一下如何制作CRC16余项表。
crc算法.pdf