CRC终于搞成了

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

今晚看了好久CRC,最后还有没有很明白。但是做为一个做工程的,有结果就好了。

我要用的不是标准的CRC公式,是X8+1这个,呵呵。下面开始总结。

CRC用到的主要是模2除法,开始看得一头雾水,只有把这个弄清楚了,后来才有了思路。才知道CRC的计算过程。(此处是重点,我费了很多劲儿理解,省去若干字。)不知道计算过程,程序是绝对不能看懂的。

还有这么一句话:多项式的MSB略去不记,因其只对商有影响而不影响余数。就是说对于CRC-CCITT=X16+X12+X5+1,可以只用0x1021,bit16位的1不要了,只留下bit12、5、0。(参考一篇modbus的说明)

记住这两点,再参考下面一段话:

生成CRC-16校验字节的步骤如下:

①装如一个16位寄存器,所有数位均为1。

②该16位寄存器的高位字节与开始8位字节进行“异或”运算。运算结果放入这个16位寄存器。

③把这个16寄存器向右移一位。

④若向右(标记位)移出的数位是1,则生成多项式1010000000000001和这个寄存器进行“异或”

运算;若向右移出的数位是0,则返回③。

⑤重复③和④,直至移出8位。

⑥另外8位与该十六位寄存器进行“异或”运算。

⑦重复③~⑥,直至该报文所有字节均与16位寄存器进行“异或”运算,并移位8次。

⑧这个16位寄存器的内容即2字节CRC错误校验,被加到报文的最高有效位。

别的都是弯路,以上是最清楚的、实惠的解释了。本文最后,附上另一位网游的文章,也给我很大启发。

下面是成功的程序:

unsigned short crc(unsigned char *addr, int num)

{

int i;

while (num--)

{

crc8 ^= *addr++;

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

{

if (crc8 & 128)

{

crc8 <<= 1;

crc8 ^= 0x01; //1010 0000 0000 0001b

}

else

{

crc8 <<= 1;

}

}

}

return crc8;

}

另外这样也行:

unsigned short crc(unsigned char *addr, int num) {

//unsigned short crc8 = 0xFF;

int i;

while (num--)

{

crc8 ^= *addr++;

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

{

if (crc8 & 1)

{

crc8 >>= 1;

crc8 ^= 0x80; //1010 0000 0000 0001b

}

else

{

crc8 >>= 1;

}

}

}

return crc8;

}

可能是因为我的x8+1只有一位的原因吧,或者什么其他的原因,我已经不愿意思考下去了。好累。注意:其中两个关键的地方就是移位1.操作不同;2.生成多项式对应的字节值不同。调整这两个变量,我想,能实现不同生成多项式的CRC算法。

另外还有查表的方式,希望以后再用到,我可以很快的搞懂。

转:

CRC 校验源码分析

这两天做项目,需要用到CRC 校验。以前没搞过这东东,以为挺简单的。结果看看别

人提供的汇编源程序,居然看不懂。花了两天时间研究了一下CRC 校验,希望我写的这点东西能够帮助和我有同样困惑的朋友节省点时间。

先是在网上下了一堆乱七八遭的资料下来,感觉都是一个模样,全都是从CRC 的数学

原理开始,一长串的表达式看的我头晕。第一次接触还真难以理解。这些东西不想在这里讲,随便找一下都是一大把。我想根据源代码来分析会比较好懂一些。

费了老大功夫,才搞清楚CRC 根据”权”(即多项表达式)的不同而相应的源代码也有稍

许不同。以下是各种常用的权。

CRC8=X8+X5+X4+1

CRC-CCITT=X16+X12+X5+1

CRC16=X16+X15+X5+1

CRC12=X12+X11+X3+X2+1

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1

以下的源程序全部以CCITT 为例。其实本质都是一样,搞明白一种,其他的都是小菜。

图1,图2 说明了CRC 校验中CRC 值是如何计算出来的,体现的多项式正是

X16+X12+X5+1。

Serial Data 即是需要校验的数据。从把数据移位开始计算,将数据位(从最低的数据位开始)逐位移入反向耦合移位寄存器(这个名词我也不懂,觉得蛮酷的,就这样写了,嘿)。当所有数据位都这样操作后,计算结束。此时,16 位移位寄存器中的内容就是CRC 码。

图1 生成CRC-CCITT 的移位寄存器的作用原理

图2 用于计算CRC_CCITT 的移位寄存器的电路配置

图中进行XOR 运算的位与多项式的表达相对应。

X5 代表Bit5,X12 代表Bit12,1 自然是代表Bit0,X16 比较特别,是指移位寄存器移出的

数据,即图中的DATA OUT。可以这样理解,与数据位做XOR 运算的是上次CRC值的Bit15。

根据以上说明,可以依葫芦画瓢的写出以下程序。(程序都是在keil C 7.10 下调试的) typedef unsigned char uchar;

typedef unsigned int uint;

code uchar crcbuff [] = { 0x00,0x00,0x00,0x00,0x06,0x0d,0xd2,0xe3};

uint crc; // CRC 码

void main(void)

{

uchar *ptr;

crc = 0; // CRC 初值

ptr = crcbuff; // 指向第一个Byte 数据

crc = crc16l(ptr,8);

while(1);

}

uint crc16l(uchar *ptr,uchar len) // ptr 为数据指针,len 为数据长度

{

uchar i;

while(len--)

{

for(i=0x80; i!=0; i>>=1)

{

if((crc&0x8000)!=0) {crc<<=1; crc^=0x1021;} 1-1

else crc<<=1; 1-2

if((*ptr&i)!=0) crc^=0x1021; 1-3

}

ptr++;

}

return(crc);

}

执行结果crc = 0xdbc0;

程序1-1,1-2,1-3 可以理解成移位前crc 的Bit15 与数据对应的Bit(*ptr&i)做XOR 运算,根

相关文档
最新文档