STM32内置CRC模块的使用

[复制链接]
62408|86
手机看帖
扫描二维码
随时随地手机跟帖
香水城|  楼主 | 2009-4-14 18:48 | 显示全部楼层 |阅读模式
所有的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寄存器,但实际上是访问的不同物理寄存器。




下面是用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
评论
高IAI阳 2018-9-20 20:02 回复TA
楼主你好经参研发现STM32F10X系列硬件CRC只支持CRC32/MPEG-2模式。 
McuIsp| | 2009-4-15 23:21 | 显示全部楼层

夜深了,出个解决方案,让stm32f的CRC32主流化:

//CopyRight:www.mcuisp.com
//版权: 单片机在线编程网
详细代码请到www.mcuisp.com下载

使用特权

评论回复
香水城|  楼主 | 2009-4-14 18:56 | 显示全部楼层

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

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

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

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

使用特权

评论回复
hotpower| | 2009-4-14 20:45 | 显示全部楼层

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

标准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

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




相关链接:https://bbs.21ic.com/upfiles/img/20094/2009414204350302.rar

使用特权

评论回复
alenthj| | 2009-4-14 20:56 | 显示全部楼层

好,收了

又省了不少flash

使用特权

评论回复
hotpower| | 2009-4-14 21:26 | 显示全部楼层

哈哈~~~菜农只差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


使用特权

评论回复
hotpower| | 2009-4-14 22:14 | 显示全部楼层

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

使用特权

评论回复
hotpower| | 2009-4-14 22:53 | 显示全部楼层

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

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

使用特权

评论回复
hotpower| | 2009-4-14 23:05 | 显示全部楼层

菜农再来证实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:21 | 显示全部楼层

CRC16/CRC32的算法各有10种之多~~~

使用特权

评论回复
hotpower| | 2009-4-14 23:29 | 显示全部楼层

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

使用特权

评论回复
McuIsp| | 2009-4-14 23:31 | 显示全部楼层

HashCalc是符合主流的:

A5A5A5A5得到结果应该是f18eb66b
STM32确实不一致.

使用特权

评论回复
McuIsp| | 2009-4-14 23:34 | 显示全部楼层

附计算工具一个:

STM32肯定也是正确的,只是不主流,呵呵
相关链接:https://bbs.21ic.com/upfiles/img/20094/200941423324768.rar

使用特权

评论回复
hotpower| | 2009-4-15 00:14 | 显示全部楼层

哈哈~~~莫非STM32和菜农一样搞非典???俺要告大鼻子去~~~

使用特权

评论回复
成成| | 2009-4-15 08:22 | 显示全部楼层

香主,我试过了,结果跟STM32一样了

非常感谢香主的鼎力支持,根据你提供的算法,我已经在PC上做了验证,结果和STM32的硬件实现一致。回头我再把我的算法和你的算法比较一下,看看问题出在哪里。


使用特权

评论回复
ijk| | 2009-4-15 10:46 | 显示全部楼层

关于CRC算法

  关于CRC算法,知其然,如果再知其所以然,事情就会清楚了。CRC算法,最重要的参数当然是生成多项式(CRC Polynomial),但(余数)初值和CRC数据最高位的位置也是很重要的两个参数,而这两个参数需要根据具体情况具体分析的。初值一般是全0或者全1,CRC数据最高位一般在最低字节的最低位或者最高位。

  CRC算法,作为一种检错算法,它的着眼点是出错概率高地方的错误,这在一定程度上决定了后两个参数。下面举例来说明。

1.串口通信在通信电缆的出错概率高,而串口数据是从LSb先发送,所以比较合理的做法是 CRC数据最高位是第1个被发送字节的最低位。如果发送的数据是"123"-0x31 0x32 0x33,那么输入的CRC数据是 1000 1100 0100 1100 1100 1100。另外,串口的缺省数据一般是1,那么比较合理的(余数)初值就是全1。

2.SPI(和I2C)通信在串行通信的出错概率高,而SPI数据(8位)一般是从MSb先发送,所以比较合理的做法是 CRC数据最高位是第1个被发送字节的最高位。如果发送的数据是"123"-0x31 0x32 0x33,那么输入的CRC数据是 0011 0001 0011 0010 0011 0011。另外,SPI的没有缺省数据,那么(余数)初值设置为全0或者全1都可以。

3.存储介质是FLASH(包括NAND、NOR、SPI FLASH),由于缺省数据(在擦除后)
是全1,比较合理的(余数)初值就是全1。

4.存储介质是硬盘,由于缺省数据(买来时)是全0,比较合理的(余数)初值就是全0。

问:SPI FLASH,比较合理的参数是什么?
答:如上所述,比较合理的(余数)初值是全1。
比较合理的做法是 CRC数据最高位是第1个字节的最高位;如果
SPI数据(8位)是从LSb先发送,比较合理的做法是 CRC数据最高位是第1个字节的最低位。

  对于STM32的32位CRC,如果假定它的一个主要目的是为了校验往内部FLASH
存储数据的可靠性,那么(余数)初值是全1当然是比较合理的。
由于STM32的32位CRC是纯32位,即每次必须输入32位的数,所以如果数据不到
32位,应该往低位用1来填充比较合理;另外,如果输入数据是"1234"-0x31 0x32 0x33 0x34,那么输入的CRC数据是 0011 0100 0011 0011 0011 0010 0011 0001,由于STM32的32位CRC是纯32位且STM32是按小端对齐(little endian)的,这也是合理的。

使用特权

评论回复
香水城|  楼主 | 2009-4-15 14:59 | 显示全部楼层

既然楼上这位朋友引用了维基百科的内容,你何不说说我哪

下面是你提到的维基百科有关如何计算CRC的说明,你总是说我做的不对,我的计算程序很简单,就放在那里供大家评判,对照维基百科的说明,你可以说说哪里不对。

使用特权

评论回复
McuPlayer| | 2009-4-15 16:44 | 显示全部楼层

ijk的帖子值得学习

使用特权

评论回复
vigia| | 2009-4-15 16:58 | 显示全部楼层

再看看维基

[編輯] 變體
CRC 有幾種不同的變體

shiftRegister 可以逆向使用,這樣就需要檢測最低位的值,每次向右移動一位。這就要求 polynomial 生成逆向的數據位結果。實際上這是最常用的一個變體。 

可以先將數據最高位讀到移位暫存器,也可以先讀最低位。在通訊協議中,為了保留 CRC 的突發錯誤檢測特性,通常按照物理層發送數據位的方式計算 CRC。
 
為了檢查 CRC,需要在全部的碼字上進行 CRC 計算,而不是僅僅計算消息的 CRC 並把它與 CRC 比較。如果結果是 0,那麼就通過這項檢查。這是因為碼字  可以被 K(x) 整除。
 
移位暫存器可以初始化成 1 而不是 0。同樣,在用演算法處理之前,消息的最初 n 個數據位要反相。這是因為未經修改的 CRC 無法區分只有起始 0 的個數不同的兩條消息。而經過這樣的反相過程,CRC 就可以正確地分辨這些消息了。 

CRC 在附加到消息數據流的時候可以進行位元反相。這樣,CRC 的檢查可以用直接的方法計算消息的 CRC、反相、然後與消息數據流中的 CRC 比較這個過程來完成,也可以通過計算全部的消息來完成。在後一種方法中,正確消息的結果不再是 0,而是  除以 K(x) 得到的結果。這個結果叫作核驗多項式 C(x),它的十六進位表示也叫作幻數。 

我觉得还是20楼的有道理,“為了保留 CRC 的突發錯誤檢測特性”

使用特权

评论回复
香水城|  楼主 | 2009-4-15 18:30 | 显示全部楼层

不要总是说这个不对,那个搞笑

你能不能拿出一个权威性的文档,说明一下有这样一个公认的标准,这个公认的标准是什么,它的实现方案又是什么样的。

总是讥讽嘲笑别人,显得你太没有水平,如果你是高人,请展示你的高明之处,谢谢!

使用特权

评论回复
hotpower| | 2009-4-15 20:30 | 显示全部楼层

Dallas/Maxim的1-Wire也很怪异,TI的PEC旧很规矩

只要和内部硬件实现有关~~~
JavaScript语言的CRC32代码摘要,详见"菜农的CRC网上在线演算器"

/*
左移crc32算法: CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1 
初值:crcvalue = 0xFFFFFFFF
权值:crcval   = 0x04C11DB7
明文:crcdword = 输入

结果:crcvalue = 输出密文
*/

function crc32l(crcdword)
{
var i,temp;
  for(i = 0; i < 32; i++){
    temp = crcvalue ^ crcdword;
    crcvalue <<= 1;
    if(temp & 0x80000000) {
      crcvalue ^= crcval;//0x04C11DB7;//CRC=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1
//注意下句是菜农针对群魔乱舞的CRC用的,STM32的CRC32权固定且最低位为1,故不需下句
//      crcvalue |= 1;//权为任意值时,保证CRC权X0=1,减少1位CRC密码强度,以便实现CRC的逆运算
    }
    crcdword <<= 1;
  }
}

现在传些成功案例的图片:
1.2个250~~~


2.stm32_crc32


3.stm32_crc32


4.stm32_crc32


5.crc8_pec


6.crc8_1-wire


7.crc8_1-wire



旧版本战例:

菜农小玩具与CRC16、PEC战斗贴图

成功完善CRC密码技术并发帖自贺且等待攻击


菜农的旧版本下载对比:https://bbs.21ic.com/upfiles/img/20094/2009414204350302.rar
相关链接:https://bbs.21ic.com/upfiles/img/20094/200941520132683.rar

使用特权

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

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17052

帖子

283

粉丝