首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

CRC 算法原理及C 语言实现(3)

CRC 算法原理及C 语言实现(3)

其中RnH4(X)是Rn(X )的高4 位,RnL12(X)是Rn(X )的低12 位。将式(5-5)代入式(5-4),经整理后得:

其中Qn-1(X)为整数,Rn-1(X)为16 位二进制余数。将式(5-7)代入式(5-6),如上类推,最后得:

    很显然,十六位二进制数R0(X)既是我们要求的CRC 码。
    式(5-7)是编写按字节计算CRC 程序的关键,它说明计算本字节后的CRC 码等于上一字节CRC码的低12 位左移4 位后,再加上上一字节余式CRC 右移4 位(也既取高4 位)和本字节之和后所求得的CRC 码,如果我们把4 位二进制序列数的CRC 全部计算出来,放在一个表里,采用查表法,每个字节算两次(半字节算一次),可以在速度和内存空间取得均衡。由此不难理解下面按半字节求CRC 码的C 语言程序。*ptr 指向发送缓冲区的首字节,len 是要发送的总字节数,CRC 余式表是按0x11021 多项式求出的。

unsigned cal_crc(unsigned char *ptr, unsigned char len) {
unsigned int crc;
unsigned char da;
unsigned int crc_ta[16]={ /* CRC 余式表 */
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
}
crc=0;
while(len--!=0) {
da=((uchar)(crc/256))/16; /* 暂存CRC 的高四位 */
crc<<=4; /* CRC 右移4 位,相当于取CRC 的低12 位)*/
crc^=crc_ta[da^(*ptr/16)]; /* CRC 的高4 位和本字节的前半字节相加后查表计算CRC,
然后加上上一次CRC 的余数 */
da=((uchar)(crc/256))/16; /* 暂存CRC 的高4 位 */
crc<<=4; /* CRC 右移4 位, 相当于CRC 的低12 位) */
crc^=crc_ta[da^(*ptr&0x0f)]; /* CRC 的高4 位和本字节的后半字节相加后查表计算
CRC,
然后再加上上一次CRC 的余数 */
ptr  ;
}
return(crc);
}
5 结束语
    以上介绍的三种求CRC 的程序,按位求法速度较慢,但占用最小的内存空间;按字节查表求CRC 的方法速度较快,但占用较大的内存;按半字节查表求CRC 的方法是前两者的均衡,即不会占用太多的内存,同时速度又不至于太慢,比较适合8 位小内存的单片机的应用场合。以上所给的C 程序可以根据各微处理器编译器的特点作相应的改变,比如把CRC 余式表放到程序存储区内等。
继承事业,薪火相传
返回列表