打印

[转贴]悟空,CRC原来是这么回事!

[复制链接]
楼主: leasor
手机看帖
扫描二维码
随时随地手机跟帖
21
xwj| | 2007-4-9 15:10 | 只看该作者 回帖奖励 |倒序浏览

直接和字节间的关系如下,好像没法进一步化简了:-(

CRC(ABCD)={ CRC(AB)<<8  ^   CRC(  (CRC(AB)/256 ^ CD ) ) }  &  0xffff;
             高字节CRC              CRC:(高字节CRC低8位^低字节
             只取低16位,高位截除
             --由于有溢出,截除的高位不知道,所以用多项式验证整个16位数得不到正确的结果了

好像没法进一步化简了,
只好按字节执行循环运算了 :-(

使用特权

评论回复
22
xwj| | 2007-4-9 15:52 | 只看该作者

整理了下多字节CRC步骤


多字节CRC步骤

 

字节3

字节2

字节1

字节0

说明

 

 

 

AB

CD

源数据

1

AB

00

00

 

高8位左移16位

2

 

CRC(AB)高

CRC(AB)低

 

高8位取模运算

 

3

 

CD

00

00

低8位左移16位

4

 

CD = CRC(AB)高 ^ CD

CD对应CRC(AB)高

5

 

 

CRC(CD)高

CRC(CD)低

低8位取模运算

6

 

 

CRC(ABCD)高

CRC(ABCD)低

高低CRC结果合并

7

 

 

CRC(ABCD) &= 0xffff;

结果只取低16位

 
下一字节运算 依次循环步骤3~7,直到位串结束。
 
 
--由于结果只取低16位,高位截除,而多字节运算是必然有溢出,截除的高位不知道,所以用多项式验证整个16位数得不到正确的结果了
 
//程序如下,全局int变量crc中保留了前一次的CRC运算结果:
uint table_crc(uchar *ptr,uchar len) // 字节查表法求CRC,查表操作就是一次CRC运算
{
    uchar da;
    while(len--!=0)
    {
        da=(uchar) (crc/256); // 以8 位二进制数暂存CRC 的高8 位
        crc<<=8;              // 左移8 位
        crc^=crc_ta[da^*ptr]; // 高字节和当前数据XOR 再查表
        ptr++;
    }
    return(crc);
}

使用特权

评论回复
23
yewuyi| | 2007-4-9 17:03 | 只看该作者

哈哈,还真俺吃着白食了……

猛啃中……

使用特权

评论回复
24
zeromicro| | 2007-4-9 21:00 | 只看该作者

模2除法是什么意思?

是除2吗?

使用特权

评论回复
25
xwj| | 2007-4-9 21:32 | 只看该作者

通过加减移位耐完成除法运算,自己去网上搜索啊

使用特权

评论回复
26
hotpower| | 2007-4-9 22:08 | 只看该作者

xwj够刻苦的~~~

使用特权

评论回复
27
dengm| | 2007-4-9 22:29 | 只看该作者

先看一下CRC的硬件电路就明白了

使用特权

评论回复
28
zeromicro| | 2007-4-11 09:58 | 只看该作者

如果多项式G(X)=X8+X5+X4+1对不对?

假设要发送的数据为0X01,按照CRC(X)=G(X)-((X)<<8)%G(X)计算得到的CRC值对吗?


如果多项式G(X)=X12+X11+X3+X2+1又对不对呢?

使用特权

评论回复
29
zeromicro| | 2007-4-11 10:07 | 只看该作者

G(X)=X8+X5+X4+1

如果要发送的数据为0X01,那么CRC的值是不是为0X5E,怎么计算得到这个值?

使用特权

评论回复
30
xwj| | 2007-4-11 10:24 | 只看该作者

呵呵,你要分清楚是左移还是右移,这两者 位的排列是不同

使用特权

评论回复
31
xwj| | 2007-4-11 10:28 | 只看该作者

8位左移可以按这个公式计算,右移的要先把位字节倒序,不如

CRC(X)=G(X)-((X)<<8)%G(X)
8位左移的G(X)为131

zeromicro 要多动脑筋哦
自己去验算下吧


8位的话还是查表最快最方便!

使用特权

评论回复
32
zeromicro| | 2007-4-11 11:04 | 只看该作者

8位左移的G(X)为0X131

8位右移的G(X)为多少?


是把0X131倒过来吗?也就是=0X119?
0X131=B‘1,0011,0001’
倒过来B‘1,0001,1001’=0X119?


资料上说计算CRC,按照这个公式计算:
     (X)·2^16               R(X)
    ----------   =  Q(X) + ----------
       G(X)                  G(X)

这个公式是左移还是右移的?
怎么得到CRC8的左移和右移的表格值?好象一般都是按照右移计算的吧?

使用特权

评论回复
33
zeromicro| | 2007-4-11 11:21 | 只看该作者

查到的一段说法……

1.2 CRC校验码的理论生成方法
  CRC校验采用多项式编码方法,被处理的数据块可以看作是一个n阶的二进制多项式。这里,假定待发送的二进制数据段为g(x),生成多项式为 m(x),得到的CRC校验码为c(x)。
  CRC校验码的编码方法是用待发送的二进制数据g(x)除以生成多项式m(x),将最后的余数作为CRC校验码,实现步骤如下。
  ① 设待发送的数据块是m位的二进制多项式 g(x),生成多项式为r阶的m(x)。在数据块的末尾添加r个0,数据块的长度增加到m+r位,对应的二进制多项式为G(x) 。
  ② 用生成多项式m(x)去除G(x) ,求得余数为阶数是r-1的二进制多项式c(x)。此二进制多项式 c(x)就是g(x)经过生成多项式m(x)编码的CRC校验码。
  ③ 用模2的方式减去c(x),得到的二进制多项式就是包含了CRC校验码的待发送字符串。

使用特权

评论回复
34
chunyang| | 2007-4-11 11:31 | 只看该作者

CRC码的计算方法

1.预置1个16位的寄存器(下称CRC寄存器),初试化其内容为十六进制数0xFFFF;
2.把第一个待计算的数据即通讯信息帧的首字节与CRC寄存器的低8位相异或,把结果放回CRC寄存器;
3.把CRC寄存器的内容右移一位用0填补最高位即进行逻辑移位处理并检查右移后的移出位;
4.如果移出位为0重复第3步即再次右移一位,如果移出位为1则CRC寄存器与CRC生成多项式0xA001(1010 0000 0000 0001)进行异或运算,结果放回CRC寄存器;
5.重复步骤3和4,直到右移8次,对整个8位数据全部进行同样处理;
6.重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
7.将该通讯信息帧所有字节按上述步骤计算完成后,最后得到的CRC寄存器的内容即为CRC校验码,将其附着在原通讯信息帧后进行传输即可。如果用于Modbus协议设备则还需交换高低8位,非Modbus协议设备可以不必交换。接收方依同样方法进行计算,只是计算的内容不要包括最后两个字节,然后比较生成的CRC校验码和数据帧中的是否相同即可。如果发送方交换CRC校验码的高低8位,则接收方可以计算包括交换后的CRC码在内的整个数据帧,传输正确的话结果恒为0x0000。

使用特权

评论回复
35
xwj| | 2007-4-11 11:51 | 只看该作者

呵呵,怎么运算的当然知道,主要是研究验算的高效简易方

使用特权

评论回复
36
zeromicro| | 2007-4-11 13:11 | 只看该作者

chunyang老师

1.预置1个16位的寄存器(下称CRC寄存器),初试化其内容为十六进制数0xFFFF;
:::预置1个16位的寄存器这是不是意味着是CRC16校验?如果是CRC8校验时是不是预置1个8位的寄存器为0XFF?
2.把第一个待计算的数据即通讯信息帧的首字节与CRC寄存器的低8位相异或,把结果放回CRC寄存器;
:::如果我要发送的数据就一个字节0X01,是不是就执行CRC=0X01^0XFF?那么执行完第二步后,CRC=0XFFFE?
3.把CRC寄存器的内容右移一位用0填补最高位即进行逻辑移位处理并检查右移后的移出位;
:::如果第二步是对的,也就是说CRC=0XFFFE,此时CRC右移一位后,CRC=0X7FFF,移出位=1?
4.如果移出位为0重复第3步即再次右移一位,如果移出位为1则CRC寄存器与CRC生成多项式0xA001(1010 0000 0000 0001)进行异或运算,结果放回CRC寄存器;
:::这个生成多项式值0xA001(1010 0000 0000 0001)对应的多项式表达式是多少?怎么推导出0XA001的?

使用特权

评论回复
37
zeromicro| | 2007-4-11 13:14 | 只看该作者

徐大师,俺连怎么算还没搞清楚呢

高效的方法更看不懂了,俺想先把最原始的计算方法弄清楚才能去看那高效的计算方法。

使用特权

评论回复
38
zeromicro| | 2007-4-11 13:21 | 只看该作者

HOTPOWER大师的那个CRC软件验证器怎么用的啊?

例如我发送的数据为0X01,使用8位左移CRC校验,那么CRC的值是多少啊?

那个初值就是填入我要发送的数据吗?那个输入输出干什么的?加权又是干什么的?点那个随机数则出来一个数值是干什么的?CRC后面的那个空框干什么的?还原按钮有什么用?复位是什么意思?
http://www.hotpower.net.cn/UploadFiles/200612222511409.htm
相关链接:http://www.hotpower.net.cn/UploadFiles/200612222511409.htm

使用特权

评论回复
39
xwj| | 2007-4-11 13:50 | 只看该作者

只要关心倒数第二行和最后一个框即可

最后一个框选择运算方式
倒数第二行:
初值是上一字节的CRC,填00;
输入本次要运算的十六进制字串,位数要是CRC算法位数的整数倍
点“计算”就能再后面的CRC框看到结果了
把结果补充到输入数后面再算的话结果就是00
比如ABCD的CRC结果是EF,那么ABCDEF的结果必然是0

使用特权

评论回复
40
zeromicro| | 2007-4-11 14:00 | 只看该作者

例如我要发送的数据为0X01

用G(X)=X8+X5+X4+1多项式计算CRC值怎么做?


在倒数第二行初值里面填00,输入填0100?
最后的CRC方式选8位右移?点计算后在CRC框得到C4,这个值对吗?好象不对把,0X01用X8+X5+X4+1计算的CRC值不是为0X5E吗?

郁闷。

请XWJ老师/chunyang老师指导。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则