标签:
最近用到STM32的CRC32模块,看一下官网的Lib,感觉用起来十分简单.但是,你会发现直接使用起来会出现,与很多在线CRC32的网站或者PC端的CRC32校验工具计算结果不一致!
简直就是无语......
搜索了一下,在21IC的论坛上面有关使用STM32的CRC32的大讨论,不过是09年的帖子.主要定论是STM32的CRC32与目前大多数的PC端软件使用的一些数据顺序及方法不一致.这里主要推荐看一下这个链接: STM32内置CRC模块的使用 讨论的很火.
如果真如,那帖子说的那样.那么作为MCU这端,是有必要进行转换,要适应潮流.当然这里不是说ST不好.
按照帖子的结论:
1、每个字节的位序相反。stm32f是按32位,高位在先。而主流实例每字节里面是从低位起的。
2、结果出来后,主流实例与0xffffffff异或了。而stm32f没有。
那么我们可以大概贴出以下代码.
/******************************************************************************* * Function Name : CRC32_ForWords * Description :输入的是32bit buffer的指针及长度 * Input : * Output : * Return : * 说明 : *******************************************************************************/ u32 CRC32_ForWords(u32 *pData,u32 uLen) { u32 i = 0,uData = 0; if((RCC->AHB1ENR & RCC_CRC_BIT) == 0) { RCC->AHB1ENR |= RCC_CRC_BIT; } /* Reset CRC generator */ CRC->CR = CRC_CR_RESET; for (i = 0;i < uLen;i++) { #ifdef USED_BIG_ENDIAN uData = __REV(*(pData + i)); #else uData = *(pData + i); #endif CRC->DR = revbit(uData); } return revbit(CRC->DR)^0xFFFFFFFF; }说明:__REV()函数功能是将数据按指节大小反向取 ,如原来的数据为0x41424344,经过这个函数之后变成0x44434241
其中,数据反向的代码(由于是GCC编译器所以不知道为什么不支持)别人的代码:
crc_16_32 revbit(crc_16_32 data) { asm("rbit r0,r0"); return data; };
/******************************************************************************* * Function Name : revbit * Description :对入参uData 按位倒序。如:0111-->1110 * Input : uData:被转的数据 * Output : None * Return : 转换好的数据 *******************************************************************************/ u32 revbit(u32 uData) { u32 uRevData = 0,uIndex = 0; uRevData |= ((uData >> uIndex) & 0x01); for(uIndex = 1;uIndex < 32;uIndex++) { uRevData <<= 1; uRevData |= ((uData >> uIndex) & 0x01); } return uRevData; }
那接着又有问题了,那如果我传入的buffer非4字节对其能否使用STM32 CRC32能.
当然,答案是肯定的.但是需要软件配合.这里直接推荐一下,我的代码参考的帖子: 实现非4字节对其的CRC32方法
我的代码如下:
#define CRC32_POLYNOMIAL ((uint32_t)0xEDB88320) #define RCC_CRC_BIT ((uint32_t)0x00001000) //#define USED_BIG_ENDIAN /*================================================================== * Function : CRC32_ForBytes * Description : CRC32输入为8bits buffer的指针及长度 * Input Para : * Output Para : * Return Value: ==================================================================*/ u32 CRC32_ForBytes(u8 *pData,u32 uLen) { u32 uIndex= 0,uData = 0,i; uIndex = uLen >> 2; if((RCC->AHB1ENR & RCC_CRC_BIT) == 0) { RCC->AHB1ENR |= RCC_CRC_BIT; } /* Reset CRC generator */ CRC->CR = CRC_CR_RESET; while(uIndex--) { #ifdef USED_BIG_ENDIAN uData = __REV((u32*)pData); #else memcpy((u8*)&uData,pData,4); #endif pData += 4; uData = revbit(uData); CRC->DR = uData; } uData = revbit(CRC->DR); uIndex = uLen & 0x03; while(uIndex--) { uData ^= (u32)*pData++; for(i = 0;i < 8;i++) if (uData & 0x1) uData = (uData >> 1) ^ CRC32_POLYNOMIAL; else uData >>= 1; } return uData^0xFFFFFFFF; }
难道CRC32这样就结束了吗?非也,还有问题.
那就是数据大小端的问题.从我的代码中,我认为如果大端的话需要将数据反一下,然后再送入到STM32 CRC32的硬件里面做运算.这样就可以得到跟PC同样的结果.
但是由于我用keil的gcc编译器,目前这个无法支持大端.所以只能当作留给有心人去帮手做剩下我结论的验证。
keil的gcc编译器编译出来的错误信息也贴上,看看有没有高手支持解决一下:
我认为目前该编译器不支持大端编译的原因是以下链接:讨论gcc大端问题 也许是支持的,自己鸡肠不够好理解错了,欢迎大家纠正.
来自:http://blog.csdn.net/lan120576664
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lan120576664/article/details/47156067