STM32F10x 学习笔记4(CRC计算单元 续)
时间:11-20
来源:互联网
点击:
上篇博客给出了 STM32F10X 系列单片机中CRC 单元的用法。还指出了这个CRC 单元计算的结果与常见的CRC32 算法得到的结果不相同。但是为什么不相同,是什么原因造成的却没有写出来。这里再补一篇,把这些都说清楚。
下面先给个crc32的计算函数,这个函数计算的结果与STM32F单片机上硬件单元的计算结果相同。
- uint32_tcrc32(uint32_t*addr,intnum,uint32_tcrc)
- {
- inti;
- for(;num>0;num--)
- {
- crc=crc^(*addr++);
- for(i=0;i<32;i++)
- {
- if(crc&0x80000000)
- crc=(crc<1)^POLY;
- else
- crc<=1;
- }
- crc&=0xFFFFFFFF;
- }
- return(crc);
- }
在我写的文章《写给嵌入式程序员的循环冗余校验(CRC)算法入门引导》(http://blog.csdn.net/liyuanbhu/article/details/7882789)中给了个利用查表法计算crc的程序。那个程序稍微修改一点就能计算CRC32。下面给出改动后的程序。
- //crc32.h
- #ifndefCRC32_H_INCLUDED
- #defineCRC32_H_INCLUDED
- #ifdef__cplusplus
- #if__cplusplus
- extern"C"{
- #endif
- #endif/*__cplusplus*/
- #include
- /*
- *TheCRCparameters.CurrentlyconfiguredforCRC32.
- *CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0
- */
- #definePOLYNOMIAL0x04C11DB7
- #defineINITIAL_REMAINDER0xFFFFFFFF
- #defineFINAL_XOR_VALUE0x00000000
- /*
- *ThewidthoftheCRCcalculationandresult.
- *Modifythetypedefforan8or32-bitCRCstandard.
- */
- typedefuint32_twidth_t;
- #defineWIDTH(8*sizeof(width_t))
- #defineTOPBIT(1<(WIDTH-1))
- /**
- *InitializetheCRClookuptable.
- *ThistableisusedbycrcCompute()tomakeCRCcomputationfaster.
- */
- voidcrcInit(void);
- /**
- *ComputetheCRCchecksumofabinarymessageblock.
- *@paramessage,用来计算的数据
- *@paranBytes,数据的长度
- *@noteThisfunctionexpectsthatcrcInit()hasbeencalled
- *firsttoinitializetheCRClookuptable.
- */
- width_tcrcCompute(unsignedchar*message,unsignedintnBytes,width_tremainder);
- #ifdef__cplusplus
- #if__cplusplus
- }
- #endif
- #endif/*__cplusplus*/
- #endif//CRC32_H_INCLUDED
对应的C程序如下:
- #include"crc32.h"
- /*
- *Anarraycontainingthepre-computedintermediateresultforeach
- *possiblebyteofinput.Thisisusedtospeedupthecomputation.
- */
- staticwidth_tcrcTable[256];
- /**
- *InitializetheCRClookuptable.
- *ThistableisusedbycrcCompute()tomakeCRCcomputationfaster.
- */
- voidcrcInit(void)
- {
- width_tremainder;
- width_tdividend;
- intbit;
- /*Performbinarylongdivision,abitatatime.*/
- for(dividend=0;dividend<256;dividend++)
- {
- /*Initializetheremainder.*/
- remainder=dividend<(WIDTH-8);
- /*ShiftandXORwiththepolynomial.*/
- for(bit=0;bit<8;bit++)
- {
- /*Trytodividethecurrentdatabit.*/
- if(remainder&TOPBIT)
- {
- remainder=(remainder<1)^POLYNOMIAL;
- }
- else
- {
- remainder=remainder<1;
- }
- }
- /*Savetheresultinthetable.*/
- crcTable[dividend]=remainder;
- }
- }/*crcInit()*/
- /**
- *ComputetheCRCchecksumofabinarymessageblock.
- *@paramessage,用来计算的数据
- *@paranBytes,数据的长度
- *@noteThisfunctionexpectsthatcrcInit()hasbeencalled
- *firsttoinitializetheCRClookuptable.
- */
- width_tcrcCompute(unsignedchar*message,unsignedintnBytes,width_tremainder)
- {
- unsignedintoffset;
- unsignedcharbyte;
- //width_tremainder=INITIAL_REMAINDER;
- /*Dividethemessagebythepolynomial,abyteatatime.*/
- for(offset=0;offset
- {
- byte=(remainder>>(WIDTH-8))^message[offset];
- remainder=crcTable[byte]^(remainder<8);
- }
- /*ThefinalremainderistheCRCresult.*/
- return(remainder^FINAL_XOR_VALUE);
- }/*crcCompute()*/
不过用这个程序直接计算得到的CRC值与STM32给出的并不相同。之所以会这样是因为字节序的原因。可以举个例子来说明这个问题。比如我们有一片内存区域要计算CRC值。这片内存区域的起始地址是0x1000,共有8个字节。用crcCompute()函数计算时是按照地址顺序依次传入各个字节。也就是先计算0x1000处的字节,再计算0x0001处的字节,以此类推最后计算0x1007地址处的字节。而STM32的硬件CRC单元是以32位的字为单位计算的。我们知道CRC实际上是个多项式的除法运算,而除法运算是从高位算起的。也就是相当于它是按照0x1003、0x1002、0x1001、0x1000这个顺序计算第一个字,然后按照0x1007、0x1006、0x1005、x1004的顺序计算第二个字。因此。我们要是预先将字节序调换一下得到结果就没有问题了。这就有了下面的改造。其中remainder传入0xffffffff。因为STM32中的CRC余数初始值为0xffffffff。
- uint32_tstm32crc32(uint32_t*message,unsig
STM32F10xCRC计算单 相关文章:
- STM32F10x 学习笔记3(CRC计算单元)(11-20)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)