【STM32学习】硬件CRC与传统CRC-32计算的不同点

本文讨论了STM32硬件CRC32与传统CRC-32在计算方法上的差异,包括字节处理方式和最终结果的不同。并提供了针对STM32硬件特性调整CRC计算的解决方案,如Crc32Calc和Crc32CalcForU8Array函数,确保数据校验的一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、stm32的硬件CRC32与传统CRC-32有何不同?

①STM32F103的硬件CRC校验是对整个32位字进行CRC计算,传统的CRC-32是逐字节的计算。
②STM32的硬件CRC32的每个字节的位序相反,STM32是按32位,高位在先,而主流实例每字节里面是从低位起的。
③最终计算结果主流实例与0xFFFFFFFF进行了异或,而STM32并没有。

对于①的解释:
将01 02 03 04 05 06 07 08作为输入。
对于传统的CRC校验而言:01 02 03 04 05 06 07 08(8个hex数据),它是一个字节一个字节的计算。
对于硬件CRC32校验而言:0x00000001 0x00000002 … 0x00000008(8个hex数据),一个32位字一个32位字进行计算。
由此可见,计算结果肯定是不同的。

对于②③的解释,见关于STM32F4xx的硬件CRC32校验

2、解决办法

上述的链接中已经详细介绍了②③的解决方法。

// MDK使用
__asm u32 Revbit (u32 data)	
{
	RBIT	R0, R0
	BX		LR
}

__asm u32 Revswap(u32 data)
{
	REV	R0, R0
	BX		LR
}

/*
RBIT:把一个32位的数据按位倒置,效果如下:

原数据 01000001 01000010 01000011 01000100,0x41424344
执行后 00100010 11000010 00100100 10000010,0x42c22482

REV:把一个32位数据的字节序改变(若芯片是小端则转为大端),效果如下

原数据 0x12345678
执行后 0x78563412
*/

对于①的解决办法:
当进行数据校验时,多数情况下,是一个uchar类型的数组。
这个数组直接输入到传统的CRC-32校验中,没有任何问题,因为它是按字节计算的。
而输入到硬件CRC中时,需要先将uchar数组按顺序拼接一个个32位字长的数据,然后输入到硬件CRC中。
例如,若uchar数组为01 02 03 04 05 06 07 08。
8个hex数据直接输入到传统CRC-32中即可。
对于硬件CRC而言,需要将数据组织为0x01020304,0x05060708,两个hex数据输入到硬件CRC中。

在这里插入图片描述

但是还有一个问题,当字节长度不是4的倍数时,组织成32位字长的数据就会留有空白。
例如,uchar类型的数组为01 02 03 04 05 06 07 08 09 0a 0b,一共11个hex数据。
那么,组合成的32位字长为0x01020304,0x05060708,0x090a0b__,最后一个字节空闲。
那么怎么解决呢?我们可以做一个约定,约定两端在进行校验时,如果有空闲存在,需要进行补充。
可以约定用0x00、0xFF进行空闲的补充。
例如,下图约定使用0x00进行补充。

在这里插入图片描述

代码分享:

/*******************************************************************************
* 函数名称: Crc32Calc()
* 功能描述: 计算CRC32,与传统的CRC-32计算结果一致
* 输入参数: 无
* 输出参数: *pucBuf 32位的数据指针缓冲区
						 ucLen  上述buf的长度
* 返 回 值: 无
* 其它说明: 
						 对32位字长数据进行计算

* 修改日期          版本号          修改人          修改内容
* ----------------------------------------------------------
* 2024/01/10        V0.01           ueueq
*******************************************************************************/
Uint32 Crc32Calc(Uint32 *pucBuf, Uint32 ucLen)
{
	Uint32 i;
	CrcReset();
	
	for (i = 0u;i<ucLen;i++)
	{
		CRC->DR = Revbit(Revswap(pucBuf[i]));   
	}
	
	return ~(Revbit(CRC->DR));
}



/*******************************************************************************
* 函数名称: Crc32CalcForU8Array()
* 功能描述: 计算CRC32,与传统的CRC-32计算结果一致
* 输入参数: 无
* 输出参数: *pucBuf 数据指针缓冲区
						 ucLen  上述buf的长度   【注意:数组长度必须为4的倍数】
* 返 回 值: 无
* 其它说明: 
						 专门用于对Uint8 aucBuf数组的计算

* 修改日期          版本号          修改人          修改内容
* ----------------------------------------------------------
* 2024/01/10        V0.01           ueueq
*******************************************************************************/
Uint32 Crc32CalcForU8Array(Uint8 *pucBuf, Uint32 ucLen)
{
	Uint32 i;
	Uint32 *puiBuf = (Uint32*)pucBuf;  // 注意这里
	
	CrcReset();
	
	ucLen = ucLen/4u;
	
	for (i = 0u;i<ucLen;i++)
	{
		CRC->DR = Revbit(puiBuf[i]);
	}
	
	return ~(Revbit(CRC->DR));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辛集电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值