前言:STM32硬件本身没有问题,只是其中的校验值计算方式跟平常的不太一样
- 硬件平台
- 我使用的是STM32F103ZET6单片机,用cubeMX新建的工程(使能crc即可加载\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_crc.c文件)
- CRC特性介绍(文档内容来自STM32中文参考手册)
- CRC32详细介绍请查看文档
- 软件平台
- 方法一:使用cubeMX初始化硬件CRC
- 方法二:手动添加文件并初始化硬件CRC
- 打开#define HAL_CRC_MODULE_ENABLED,在.\Core\Inc\stm32f1xx_hal_conf.h中第42行
- 添加源文件stm32f1xx_hal_crc.c到工程中
- 再主函数添加初始化程序
CRC_HandleTypeDef hcrc;
/* CRC32初始化函数 */
static void MX_CRC_Init(void);
/* 软件方式计算CRC32-STM32 */
uint32_t uiCRC32_STM32(uint32_t *puiInitCRC, uint32_t *pucDataBuff, uint32_t uiLength)
{
uint32_t uiPolynomial = 0x04C11DB7, uiInputCRC = 0xFFFFFFFF, i = 0, xbit = 0x80000000, uiMask = 0, uiDataTemp = 0;
if(puiInitCRC != NULL)
uiInputCRC = *puiInitCRC;
for(i = 0; i < uiLength; ++i)
{
uiDataTemp = *pucDataBuff++;
xbit = 0x80000000;
for(uiMask = 1; uiMask; uiMask <<= 1)
{
if(uiInputCRC & 0x80000000)
uiInputCRC = (uiInputCRC << 1) ^ uiPolynomial;
else
uiInputCRC <<= 1;
if(uiDataTemp & xbit)
uiInputCRC ^= uiPolynomial;
xbit >>= 1;
}
}
return uiInputCRC;
}
uint32_t CRC32 = 0, blen = 0, uiCRC32 = 0;
void HAL_CRC32_Test(void)
{
/* 第一步,必须使能硬件CRC32 */
__HAL_RCC_CRC_CLK_ENABLE();
/* 第二步,使用硬件CRC计算CRC32值 */
char *pbuf = "SET,123456,50,000164,";
blen = strlen(pbuf);
CRC32 = HAL_CRC_Calculate(&hcrc, (uint32_t *)pbuf, blen);
/* 第三步,对比软件方式去计算CRC32 */
uiCRC32 = uiCRC32_STM32(NULL, (uint32_t *)pbuf, blen);
/* 第四步, 对比CRC32与uiCRC32, 结果发现值相等 */
}
int main(void)
{
...
MX_CRC_Init();
/* 计算CRC32 */
HAL_CRC32_Test():
...
}
/**
* @brief CRC Initialization Function
* @param None
* @retval None
*/
static void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
备注:常用CRC32与CRC32-MPEG2.0计算代码如下
/* 常用CRC32校验算法 */
uint32_t uiReflect(uint32_t uiData, uint8_t ucLength)
{
uint32_t uiMask = 1 << (ucLength - 1), uiMaskRef = 1, uiDataReturn = 0;
for(; uiMask; uiMask >>= 1)
{
if(uiData & uiMask)
uiDataReturn |= uiMaskRef;
uiMaskRef <<= 1;
}
return uiDataReturn;
}
uint32_t uiCRC32(uint32_t *puiInitCRC, uint8_t *pucDataBuff, uint32_t uiLength)
{
uint32_t uiPolynomial = 0x04C11DB7, uiInputCRC = 0xFFFFFFFF, i = 0;
uint8_t ucMask = 0;
if(puiInitCRC != NULL)
uiInputCRC = *puiInitCRC;
uiPolynomial = uiReflect(uiPolynomial, 32);
for(i = 0; i < uiLength; ++i)
{
uiInputCRC ^= *pucDataBuff++;
for(ucMask = 1; ucMask; ucMask <<= 1)
{
if(uiInputCRC & 1)
uiInputCRC = (uiInputCRC >> 1) ^ uiPolynomial;
else
uiInputCRC >>= 1;
}
}
return ~uiInputCRC;
}
/* CRC32-MPEG2.0校验算法 */
uint32_t uiCRC32_MPEG2(uint32_t *puiInitCRC, uint8_t *pucDataBuff, uint32_t uiLength)
{
uint32_t uiPolynomial = 0x04C11DB7, uiInputCRC = 0xFFFFFFFF, i = 0;
uint8_t ucMask = 0;
if(puiInitCRC != NULL)
uiInputCRC = *puiInitCRC;
for(i = 0; i < uiLength; ++i)
{
uiInputCRC ^= (uint32_t)(*pucDataBuff++) << 24;
for(ucMask = 1; ucMask; ucMask <<= 1)
{
if(uiInputCRC & 0x80000000)
uiInputCRC = (uiInputCRC << 1) ^ uiPolynomial;
else
uiInputCRC <<= 1;
}
}
return uiInputCRC;
}