原创 菜农只差crc64没过招了~~~

2009-4-15 00:16 3910 4 3 分类: MCU/ 嵌入式

原帖讨论:http://bbs.21ic.com/club/bbs/list.asp?boardid=49&t=3302129


香水城 发表于 2009-4-14 18:48 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖


楼主: STM32内置CRC模块的使用


所有的STM32芯片都内置了一个硬件的CRC计算模块,可以很方便地应用到需要进行通信的程序中,这个CRC计算模块使用常见的、在以太网中使用的计算多项式:
  X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1
写成16进制就是:0x04C11DB7

使用这个内置CRC模块的方法非常简单,既首先复位CRC模块(设置CRC_CR=0x01),这个操作把CRC计算的余数初始化为0xFFFFFFFF;然后把要计算的数据按每32位分割为一组数据字,并逐个地把这组数据字写入CRC_DR寄存器(既下图中的绿色框),写完所有的数据字后,就可以从CRC_DR寄存器(既下图中的兰色框)读出计算的结果。

注意:虽然读写操作都是针对CRC_DR寄存器,但实际上是访问的不同物理寄存器。

2009414182656610.gif




下面是用C语言描述的这个计算模块的算法,大家可以把它放在通信的另一端,对通信的正确性进行验证:

DWORD dwPolynomial = 0x04c11db7;
DWORD cal_crc(DWORD *ptr, int len)
{
    DWORD    xbit;
    DWORD    data;
    DWORD    CRC = 0xFFFFFFFF;    // init
    while (len--) {
        xbit = 1 << 31;

        data = *ptr++;
        for (int bits = 0; bits < 32; bits++) {
            if (CRC & 0x80000000) {
                CRC <<= 1;
                CRC ^= dwPolynomial;
            }
            else
                CRC <<= 1;
            if (data & xbit)
                CRC ^= dwPolynomial;

            xbit >>= 1;
        }
    }
    return CRC;
}


有几点需要说明:

1)上述算法中变量CRC,在每次循环结束包含了计算的余数,它始终是向左移位(既从最低位向最高位移动),溢出的数据位被丢弃。

2)输入的数据始终是以32位为单位,如果原始数据少于32位,需要在低位补0,当然也可以高位补0。

3)假定输入的DWORD数组中每个分量是按小端存储。

4)输入数据是按照最高位最先计算,最低位最后计算的顺序进行。

例如:
如果输入0x44434241,内存中按字节存放的顺序是:0x41, 0x42, 0x43, 0x44。计算的结果是:0xCF534AE1
如果输入0x41424344,内存中按字节存放的顺序是:0x44, 0x43, 0x42, 0x41。计算的结果是:0xABCF9A63

香水城 发表于 2009-4-14 18:56 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

2楼: 前几天有网友网上抄了一个算法,但始终没有得到正确的结果


我没有仔细地分析具体原因,但大体看起来应该是移位的方向反了,不太理解它的Reflect()函数的作用。

如果大家有兴趣可以去看看,那个C语言实现的算法是使用查表方式,效率比较高,但需要一个1K字节的存储空间。

请教香主,STM32有内置的硬件CRC计算单元吗?

hotpower 发表于 2009-4-14 20:45 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

3楼: 菜农贴图证明香主给的答案是对的~~~


标准CRC生成多项式如下表:

   名称        生成多项式              简记式*   标准引用
   CRC-4       x4+x+1                  3         ITU G.704
   CRC-8       x8+x5+x4+1              0x31                    
   CRC-8       x8+x2+x1+1              0x07                    
   CRC-8       x8+x6+x4+x3+x2+x1       0x5E
   CRC-12      x12+x11+x3+x+1          80F
   CRC-16      x16+x15+x2+1            8005      IBM SDLC
   CRC16-CCITT x16+x12+x5+1            1021      ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
   CRC-32      x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
   CRC-32c     x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP


注意:crc32的“权”本为0x04C11DB7
由于俺的内部处理(主要为了加密和解密),故将其右移1位
即得到图中的0x02608edb.

设置时,选crc32左移方式后,将初值设为0xffffffff

再输入大端模式的计算值。如图所示:

点击看大图

点击看大图


菜农的CRC网上通用演算器


hotpower 发表于 2009-4-14 21:26 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

5楼: 哈哈~~~菜农只差crc64没过招了~~~


标准CRC生成多项式如下表:

   名称        生成多项式              简记式*   标准引用
   CRC-4       x4+x+1                  3         ITU G.704
   CRC-8       x8+x5+x4+1              0x31                    
   CRC-8       x8+x2+x1+1              0x07                    
   CRC-8       x8+x6+x4+x3+x2+x1       0x5E
   CRC-12      x12+x11+x3+x+1          80F
   CRC-16      x16+x15+x2+1            8005      IBM SDLC
   CRC16-CCITT x16+x12+x5+1            1021      ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
   CRC-32      x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
   CRC-32c     x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP

菜农的CRC网上通用演算器基本战法:

1.CRC8(1-Wire bus) 菜农选: 初值=0 权=0x18 右移crc8
CRC-8       x8+x5+x4+1

2.PEC(HDQ16) 菜农选:初值=0 权=0x03 左移crc8
CRC-8       x8+x2+x1+1

3.CRC16-CCITT  菜农选:初值=0 权=0x0810 左移crc16
CRC16-CCITT x16+x12+x5+1

4.CRC-32(STM32) 菜农选:初值=0xffffffff 权=0x02608edb 左移crc32
CRC-32      x32+x26+x23+...+x2+x+1

Netjob 发表于 2009-4-14 22:07 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

6楼: 好笑!你不按标准,还说对的?


CRC-32是个标准, PC上好多文件的校验都是按这个CRC-32标准。

这个不是好笑吗? ST的这个CRC32算出的结果竟然与PC的标准不一样,

大家说好不好笑?

hotpower 发表于 2009-4-14 22:14 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

7楼: 不好笑~~~关键是stm32的CRC32初值非零有点怪~~~

Netjob 发表于 2009-4-14 22:44 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

8楼: 不好笑?


怪胎呢!

hotpower 发表于 2009-4-14 22:53 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

9楼: CRC的结果由初值、权和输入值决定了输出即CRC结果


让俺是STM32的CRC设计师肯定把初值搞几个250~~~

香水城 发表于 2009-4-14 22:53 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

10楼: 6楼这位朋友:你先不要嘲笑谁


请先把你的好几个PC校验文件的计算程序亮出来看看,我的计算算法已经摆出来了,大家可以对比一下谁对谁错。




我在网上找到一些有关的资料,在此分享一下,也作为我给出的算法的佐证:

1)实用资料——CRC计算方法--春阳频道——这里描述了CRC16的计算方法,但同样适合于其它多项式算法。这里同时提出需要初始化计算余数为0xFFFF。

2)CRC计算方法与C实现——在这篇文章的第2部分(硬件电路的实现方法),也明确提出“编码、解码前将各位初始化为1”。

3)下面这段话是我从USB 1.1协议文本的8.3.5节中抄下来的,这里也明确写明初始化为全'1',和数据高位先参与计算的原则:
For CRC generation and checking, the shift registers in the generator and checker are seeded with an all ones
pattern. For each data bit sent or received, the high order bit of the current remainder is XORed with
the data bit and then the remainder is shifted left one bit and the low-order bit set to zero. If the result of
that XOR is one, then the remainder is XORed with the generator polynomial.

我相信你还可以从网上搜索出很多这样的说明,我无法评判网上那些程序的正确性,但我可以证明我给出的程序是正确的。

hotpower 发表于 2009-4-14 23:05 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

11楼: 菜农再来证实STM32的CRC32是正确的~~~自己看看算法吧~~~


成成 发表于 2009-3-31 16:08 ST MCU ←返回版面    

20楼: 我用STM32算出来的结果和程序算出来的结果都不一样

STM32:
1、把STM32的寄存器复位,复位后的值为0xFFFFFFFF
2、按照双字操作方式,直接把0xA5A5A5A5写入DR寄存器
3、读取DR的结果为:0x29928E70
这跟Netjob你给的结果不一样

我的算法计算出的结果是:0xF9494ABA
这也跟Netjob你给的结果不一样





点击看大图


hotpower 发表于 2009-4-14 23:29 ST MCU ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

14楼: 菜农也认为意法大鼻子的水平肯定高过菜农,所以STM32的CRC无错!

 


菜农的CRC专栏

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条