STM32 CRC实验详解
1.CRC
1.1基本概念
1.1.1CRC的简介
数据传输过程中是否出错。
式,把运算得到的余数用二进制数表示,这个二进制数就是CRC校验值。
1.1.2CRC的框图
(1)用作输入寄存器,向CRC计算器中输入新数据 (向寄存器写入数据时)
(2)可保存之前的CRC计算结果 (读取寄存器时)
使用CRC_CR寄存器中的RESET控制位即可将CRC计算器复位为0xFFFF FFFF。此操作不影响CRC_IDR寄存器的内容
1.1.3CRC的计算和校验
1.2HAL的API函数
1.2.1API功能函数
(1)以前一次CRC校验的结果作为初始值继续进行校验 (适用于连续多次校验的第2、3、4… …次)
uint32_t HAL_CRC_Accumulate (CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
*hcrc:
指向
CRC_HandleTypeDef CRC
校验总控制结构体的指针pBuffer:待校验的数据
BufferLength:待校验的数据长度
返回值:校验结果
该函数在第一使用时需要调用HAL_CRC_Calculate,计算出第一次数据的校验位,然后由第一位的数据位的校验位作为下一位的的初始值。计算出最后一位的数据位作为整个传递数据的校验位
(2)使用默认初始值进行校验计算 (适用于单次校验 or 多次校验的第一次)
uint32_t HAL_CRC_Calculate (CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
该函数一次性将全部数据的校验位检测出来,且初值仍为0xFFFFFFFF
(3)获取状态的函数
HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc
返回值:CRC校验总控制结构体内的
State
值、即
HAL_CRC_STATE_RESET 尚未初始化
HAL_CRC_STATE_READY 初始化并准备使用
HAL_CRC_STATE_BUSY 忙
HAL_CRC_STATE_TIMEOUT 超时
HAL_CRC_STATE_ERROR 错误
1.2.1API宏定义
(1)复位CRC数据寄存器
__HAL_CRC_DR_RESET(__HANDLE__)
关联寄存器 CRC_CR 位
0 RESET
置位 设置数据寄存器为0xFFFFFFFF(2)临时存放1字节的数据到IDR寄存器
__HAL_CRC_SET_IDR(__HANDLE__, __VALUE__)
__VALUE__
(待存放的数据)关联寄存器 CRC_IDR 存放临时数据
(3)复位CRC总控结构体中状态变量State变量复位成HAL_CRC_STATE_RESET
__HAL_CRC_RESET_HANDLE_STATE(__HANDLE__)
(4)读取IDR寄存器临时存放的1字节数据
__HAL_CRC_GET_IDR(__HANDLE__)
1.3CRC的实验
硬件本身的多项式和初始值的函数
/* USER CODE BEGIN 2 */
uint32_t a;
uint32_t b;
uint32_t CRCBUF[4]={0x66203040,0x66230301,0x67337923,0x68328923};//数据寄存器的要校验的数据。
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
a=HAL_CRC_Calculate(&hcrc,(uint32_t *)CRCBUF,4);//一次性计算出数据寄存器CRCBUF的CRC的校验,初始值为0xFFFFFFFF
printf("单次检测的值:a=%x\r\n",a);
/*计算CRC硬件的校验位*/
HAL_CRC_Calculate(&hcrc,&CRCBUF[0],1);//先计算出数据寄存器CRCBUF[0]的CRC的校验,再传递给CRCBUF[1],初始值为0xFFFFFFFF
HAL_CRC_Accumulate(&hcrc,&CRCBUF[1],1);
HAL_CRC_Accumulate(&hcrc,&CRCBUF[2],1);
b=HAL_CRC_Accumulate(&hcrc,&CRCBUF[3],1);
printf(" 连续检测的值:b=%x\r\n",b);
HAL_Delay(500);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
自定义CRC函数(多项式和初始值)
//init为初始值FFFFFFFF,len为字节长度,data每次传送一个2字节
uint32_t CRC32(uint8_t *data,uint16_t len,uint32_t init)
{
uint32_t poly=0x04C11DB7; //硬件CRC32的多项式
uint8_t i;
while(len--)//一个字节一个字节的计算
{
init=init^(*data<<24);//左移到最高处后和初值异或,结果变为新初值
for(i=0;i<8;i++) //每次计算一位
{
if(init&80000000) //if成立,二进制数为1
{
init=(init<<1)^poly;//位数为1,则与多项式进行异或
}
else //不成立此时二进制为0
{
init=(init<<1);//此时仅需左移就行
}
data++; //地址递增,一次是2个字节
}
}
return init; //此时返回校验值
}
视频链接:
这里我推荐两个视频非常清晰,听完你将会对CRC,存在更加清楚(完美)
https://www.bilibili.com/video/BV1iV411G7Fj/?spm_id_from=333.880.my_history.page.click&vd_source=195bd65089e0a59a3daa9222f1c3a6fd
https://www.bilibili.com/video/BV1HH4y1A7Ww/?spm_id_from=333.337.search-card.all.click&vd_source=195bd65089e0a59a3daa9222f1c3a6fd
作者:人间一缕风十万八千梦