CRC算法原理(2)

2019-06-17 16:04

/* 求数据的CRC校验码 */ for (i=0; i<8; i++) {

if (crc & 0x8000) /* 最高位为1,减去除数 */ {

crc <<= 1; crc ^= ccitt16; }

else /* 最高位为0,不需要减去除数 */ {

crc <<= 1; /* 直接移位 */ } }

return crc; }

/* 这是个主程序,表示如何计算5个字节的CRC */ void main() {

int i;

unsigned short crc;

char data[5] = { 0x71, 0x88, 0x93, 0xa5, 0x13 }; /* 计算这5个数据的CRC校验码 */

crc = 0;

for (i=0; i<5; i++) {

crc = crc16_ccitt(data[i], crc);

}

printf(\}

好了,讲到这里CRC算法已经全部介绍完了。什么,讲完了?不对呀,我怎么记得CRC程序都有个数组叫CRC表什么的,你这里怎么没有?

呵呵,其实使用CRC表是为了节省一些运算时间,事先将算好的CRC保存在数组里,省得临时再计算,它保存的是0到0xff的CRC码,下面我们来自己生成一个CRC表: unsigned short CRC16_CCITT_TABLE[256];

void init_crc16_ccitt_table() {

int i;

for (i=0; i<256; i++) {

CRC16_CCITT_TABLE[i] = crc16_ccitt(i, 0); } }

上面只是一个字节的CRC表,那多个字节的CRC如何计算呢?与前面求多字节的CRC方法差不多,它的代码如下:

/* 这段代码是查表求ccitt-crc16的算法,它与前面的程序crc16_ccitt所得到的结果一样 参数: data:字节数据

crc:原来数据求得的crc校验码 返回值:

数据的ccitt-crc16校验码

*/

unsigned short crc16_ccitt_2(unsigned char data, unsigned short crc) {

unsigned char c;

c = crc >> 8; /* c的值为crc的高8位 */

crc <<= 8; /* crc现在的值变为低8位左移8位 */ crc ^= CRC16_CCITT_TABLE[data ^ c]; return crc; }

最后要说的是CRC的正序和反转问题,比如前面ccitt-crc16的正序是0x1021,如果是反转就是0x8408(就是将0x1021倒过来低位变高位)为什么要反转?这是因为数据传输可能是先传低位再传高位(比如串口就是低位在前高位在后)。反转的CRC算法与正序类似,只是需要注意移位的方向相反。

/* 这段代码是求ccitt-crc16的反转算法 参数: data:字节数据

crc:原来数据求得的crc反转校验码 返回值:

数据的ccitt-crc16反转校验码 */

unsigned short crc16_ccitt_r(unsigned char data, unsigned short crc) {

unsigned short ccitt16 = 0x8408;

int i;

crc ^= data; /* 新的数据与将原来的余数(就是crc)相加(加法就是异或操作)

*/

for (i=0; i<8; i++) {

if (crc & 1) /* 最低位为1,减去除数 */ {

crc >>= 1; crc ^= ccitt16; }

else /* 最低位为0,不需要减去除数 */ {

crc >>= 1; /* 直接移位 */ } }

return crc; }

/* 这段代码是查表求反转ccitt-crc16的算法,它与前面的程序crc16_ccitt_r所得到的结果一样 参数: data:字节数据

crc:原来数据求得的crc校验码 返回值:

数据的ccitt-crc16校验码 */

unsigned short crc16_ccitt_r2(unsigned char data, unsigned short crc) {

unsigned char c;

c = crc & 0xff; crc >>= 8;

crc ^= CRC16_CCITT_R_TABLE[data ^ c]; return crc; }

CRC算法及原理

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

信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。 在数据存储和数据通讯领域,CRC无处不在:著名的通讯协议X.25的FCS(帧检错序列)采用的是CRC. CCITT,ARJ、LHA等压缩工具软件采用的是CRC32,磁盘驱动器的读写采用了CRC16,通用的图像存储格式GIF、TIFF等也都用CRC作为

检错手段。

CRC的本质是模-2除法的余数,采用的除数不同,CRC的类型也就不一样。通

常,CRC的除数用生成多项式来表示。最常用的CRC码的生成多项式有

CRC16,CRC32.

以CRC16为例,16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(既乘以2^16)后,再除以一个多项式,最后所得到的余数既是CRC码,如下式所示,其中K(X)表示n位的二进制序列数,G(X)为多项式,Q(X)为整数,

R(X)是余数(既CRC码)。 K(X)>>16=G(x)Q(x)+R(x)

求CRC码所采用模2加减运算法则,既是不带进位和借位的按位加减,这种加减运算实际上就是逻辑上的异或运算,加法和减法等价,乘法和除法运算与普通代数式的乘除法运算是一样,符合同样的规律。生成CRC码的多项式如下,其中CRC-16和CRC-CCITT产生16位的CRC码,而CRC-32则产生的是32位的CRC

接收方将接收到的二进制序列数(包括信息码和CRC码)除以多项式,如果余数为0,则说明传输中无错误发生,否则说明传输有误,关于其原理这里不再多述。用软件计算CRC码时,接收方可以将接收到的信息码求CRC码,比较结果和接收

到的CRC码是否相同。

CCITT推荐的高级数据链路控制规程HDLC的帧校验序列FCS中,使用CCITT-16即CRC16,其生成多项式为G(x)=x16+x12+x5+1, CRC-32的生成多项式为

G(x)=x32+x26+x23+x22+x16+x11+x10+x16+x8+x7+x5+x4+x2+x+1


CRC算法原理(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:新版人教版小学数学四年级下册《三角形特性》教学设计

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: