打印
[APM32F4]

APM32F4xx CRC应用

[复制链接]
449|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1455555|  楼主 | 2023-7-24 10:44 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 1455555 于 2023-7-24 10:44 编辑

1、CRC 简介
CRC,全称是 Cyclic Redundancy Check ,即循环冗余校验码。该单元可将输入数据经过固定的多项式计算得到 32 位的 CRC 计算结果,主要用来检测或校验数据传输或者保存后的正确性与完整性。
1.1 CRC 参数模型
计算一个正确的准确的CRC 值,需要知道CRC 的参数模型,将待校验数据输入,根据参数模型通过CRC 算法进行计算,最终得到校验值。一个完整的CRC参数模型应该包含以下信息:WIDTHPOLYINITREFINREFOUTXOROUT。 其中:
1NAME:参数模型名称。
2WIDTH:宽度,即生成的 CRC 数据位宽,如 CRC-8,生成的 CRC 8位。
3POLY:十六进制多项式,省略最高位 1,如 x8 + x2 + x + 1,二进制为 1 0000 0111,省略最高位 1,转换为十六进制为 0x07
4INITCRC 初始值,和 WIDTH 位宽一致。
5REFINtrue false,在进行计算之前,原始数据是否翻转,如原始数据:
0x34 = 0011 0100,如果 REFIN true,进行翻转之后为 0010 1100 = 0x2c
6REFOUTtrue false,运算完成之后,得到的 CRC 值是否进行翻转, 如计算得到的 CRC 值:0x97 = 1001 0111,如果 REFOUT true,进行翻转之 后为 11101001 = 0xE9
7XOROUT:计算结果与此参数进行异或运算后得到最终的 CRC 值,和WIDTH 位宽一致。 通常如果只给了一个多项式,其他的没有说明则:INIT=0x00REFIN=false
REFOUT=falseXOROUT=0x00
1.1.1 常用 CRC 参数模型
关于 CRC 常用参数模型及其应用场合如表 1 所示。1 常用 CRC 介绍
CRC算法名称
多项式公式/16进制多项式
16进制
多项式
输入值反转
输出值反转
CRC-5/ITU
15
true
true
CRC-5/USB
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps2.jpg
05
true
true
CRC-7/MMC
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps3.jpg
09
false
false
CRC-8/ITU
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps4.jpg
07
false
false
CRC-16/USB
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps5.jpg
8005
true
true
CRC-16/
MODBUS
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps6.jpg
8005
true
true
CRC-32/
MPEG-2
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps7.jpg
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps8.jpg
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps9.jpg
04C11DB7
false
false
CRC-32
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps10.jpg
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps11.jpg
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml5288/wps12.jpg
04C11DB7
true
true
1.2 CRC 算法
CRC 的概念是在待发送的 K 比特数据的末尾添加一个 R 比特的校验码,并生成一个新的帧发送给接收端。接收端接收到新帧后,通过校验码对接收到的数据进行验证,以确定数据是否正确。为了实现这一点,发送端和接收端需要共同选择一 个特定的除数,通过"2 除法"将生成的新帧除以这个除数。接收端将接收到的新 帧除以选定的除数。由于在发送数据帧之前已经通过添加一个数进行了"去余"处理 (也就是整除),所以结果应该是没有余数的。如果存在余数,则说明该帧在传输 过程中发生了错误。具体步骤如下:
1)发送端、接收端在通信前,约定好除数 P,也就是前面说的多项式的值。P 应该是 R+1 位长度;
2)发送端在原来的 K 位数据后面加 R 0,将原来的数据左移 R 位;
3)进行模 2 除法运算,也就是异或 XOR 运算。将加 0 之后的 K+R 位的数除 以 P,循环计算,直到余数的阶数小于 R,这个余数就是附加的校验码,如果长度 不足 R 位需要在前面加 0 补齐;
4)发送端将 R 位校验码附加在原数据后面发送给接收方;
5)接收方接收到数据后,将数据以模 2 除法方式除以除数 P。如果没有余数, 说明在传输过程中没有出现错误,否则说明有错误。 以 CRC-4=X4+X+1 为例,此时除数 P=10011。假设源数据 M 10110011。 在发送端将 M 左移 4 位,然后除以 P。计算过程如图 1,图 2 所示。

1 发送端 CRC 计算示例

2 接收端 CRC 计算示例
计算得到的余数就是 0100,也就是 CRC 校验码。将 0100 附加到原始数据帧10110011 后,组成新帧 101100110100 发送给接收端。接收端接收到该帧后,会用该帧去除以上面选定的除数P,验证余数是否为0,如果为0,则表示数据在传 输过程中没有出现差错。 其中 CRC-MSBCyclic Redundancy Check - Most Significant Bit)是一种特 殊的校验算法,其计算过程从最高位(Most Significant Bit)开始。当 CRC 的最 高位为 1 时,该算法将 CRC 向左移一位,并与预设的多项式进行异或(XOR)计算。如果 CRC 的最高位为 0,则只将CRC 向左移一位。

2 APM32F4XX CRC 介绍
2.1 APM32F4XX CRC 参数模型
APM32 自带的硬件 CRC 计算模块使用的是 CRC-32 模型,其多项式为
0x4C11DB7——X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 + X8 + X7 + X4 + X2 + X +1。 按照前文内容[size=13.9333px]1.1 提及的模型参数分析说明:APM32 CRC 数据位宽为 32 位, 十六进制多项式为 0x4C11DB7INIT=0xFFFFFFFFREFIN=falseREFOUT=falseXOROUT=0x00000000
2.2 硬件实现优势
APM32 自带的硬件 CRC 计算模块,使用硬件实现 CRC 带来以下一些优势:
1)高速计算:硬件实现 CRC 可以利用专门的电路和并行计算来实现快速的
CRC 计算。相比于软件实现,硬件可以在几个时钟周期内完成 CRC 计算,提供更高的处理速度。
2)低功耗:由于使用了专门的电路来执行 CRC 计算,硬件实现可以通过电 路设计的优化来降低功耗。相比于在软件中使用循环来计算CRC,硬件实现可以节省大量的能量。
3)占用资源少:软件实现 CRC 可能需要较大的存储器和处理器资源来执行 复杂的计算。而硬件实现通常只需要一些逻辑门和寄存器,占用的资源较少,尤其 适用于资源有限的嵌入式系统。
4)实时性:硬件实现的 CRC 可以在实时数据流中进行连续计算,没有延迟 或中断。这对于需要快速处理数据流的应用非常重要,如实时传输、通信协议等。
5)硬件抗干扰能力强:硬件实现的 CRC 通常能够更好地抵御噪声和干扰, 因为它可以采用差分信号和物理层技术来提高抗干扰能力。这对于数据传输的可靠性和错误检测非常重要。综上,CRC 的硬件实现具有高速计算、低功耗、占用资源少、实时性好以及较强的抗干扰能力等优势。这使得硬件实现在需要高效率、可靠性和实时性的应用 中更加有优势。

3 APM32F4XX CRC 应用例程
3.1 软件设计流程
APM32F4XX 例程中已根据数据算出标准校验值,网页计算过程如图 3 所示, 计算得标准校验值为 0x379E9F06。将待校验数据串存放在数组中,进行 CRC 校验,当输出校验值与标准校验值相等时,证明传输正常;反之,二者不同时证明数 据传输出错。
3 标准校验值计算
CRC 计算单元包含一个32 位的数据寄存器(CRC_DATA),用于进行数据输入和保存 CRC 计算结果。其计算时间为 4 AHB 时钟周期。每写入一次新数 、据,其结果是上一次的计算结果和新的计算结果的组合,(对整个字进行运算)。 在计算期间,会暂停 CPU 的写操作,因此可以对寄存器 CRC_DATA 进行背靠 背写入或连续地读—写操作。要计算支持数据的 CRC,需要按照以下步骤进行 操作: 1) 通过 RCC 外设启用 CRC 外设时钟。
2) 配置初始 CRC 值寄存器(CRC_DATA)将 CRC 数据寄存器设置为初始CRC 值。
3) 通过 CRC 控制寄存器(CRC_CTRL)中的 Reset 位将 CRC 外设重置。
4) 将数据设置到 CRC 数据寄存器。
5) 读取 CRC 数据寄存器的内容,即为计算得到的 CRC 值。 软件编写流程图如下:

4 CRC 软件编写流程图
3.2 软件实现
3.2.1 CRC 参数定义
定义数组存放待校验数据,定义 32 位整型变量用于存储 CRC 输出校验值; 同时完成串口初始化及相关参数设定:将波特率设置为 115200,校验位为 0,停止位为 1 等。相关代码如下:
static const uint32_t aDataBuffer[BUFFER_SIZE] = {
0x00001021, 0x20423063, 0x408450a5, 0x60c670e7, 0x9129a14a,
0xb16bc18c, 0xd1ade1ce, 0xf1ef1231, 0x32732252, 0x52b54294,
0x72f762d6, 0x93398318, 0xa35ad3bd, 0xc39cf3ff, 0xe3de2462,
0x34430420, 0x64e674c7, 0x44a45485, 0xa56ab54b, 0x85289509,
0xf5cfc5ac, 0xd58d3653, 0x26721611, 0x063076d7, 0x569546b4,
0xb75ba77a, 0x97198738, 0xf7dfe7fe, 0xc7bc48c4, 0x58e56886,
0x78a70840, 0x18612802, 0xc9ccd9ed, 0xe98ef9af, 0x89489969,
0xa90ab92b, 0x4ad47ab7, 0x6a961a71, 0x0a503a33, 0x2a12dbfd,
0xfbbfeb9e, 0x9b798b58, 0xbb3bab1a, 0x6ca67c87, 0x5cc52c22,
0x3c030c60, 0x1c41edae, 0xfd8fcdec, 0xad2abd0b, 0x8d689d49,
0x7e976eb6, 0x5ed54ef4, 0x2e321e51, 0x0e70ff9f, 0xefbedfdd,
0xcffcbf1b, 0x9f598f78, 0x918881a9, 0xb1caa1eb, 0xd10cc12d,
0xe16f1080, 0x00a130c2, 0x20e35004, 0x40257046, 0x83b99398,
0xa3fbb3da, 0xc33dd31c, 0xe37ff35e, 0x129022f3, 0x32d24235,
0x52146277, 0x7256b5ea, 0x95a88589, 0xf56ee54f, 0xd52cc50d,
0x34e224c3, 0x04817466, 0x64475424, 0x4405a7db, 0xb7fa8799,
0xe75ff77e, 0xc71dd73c, 0x26d336f2, 0x069116b0, 0x76764615,
0x5634d94c, 0xc96df90e, 0xe92f99c8, 0xb98aa9ab, 0x58444865,
0x78066827, 0x18c008e1, 0x28a3cb7d, 0xdb5ceb3f, 0xfb1e8bf9,
0x9bd8abbb, 0x4a755a54, 0x6a377a16, 0x0af11ad0, 0x2ab33a92,
0xed0fdd6c, 0xcd4dbdaa, 0xad8b9de8, 0x8dc97c26, 0x5c644c45,
0x3ca22c83, 0x1ce00cc1, 0xef1fff3e, 0xdf7caf9b, 0xbfba8fd9,
0x9ff86e17, 0x7e364e55, 0x2e933eb2, 0x0ed11ef0
};
uint32_t uCRCValue = 0;
USART_Config_T usartConfigStruct; /* USART configuration */
USART_ConfigStructInit(&usartConfigStruct);
usartConfigStruct.baudRate = 115200;
usartConfigStruct.mode = USART_MODE_TX_RX;
usartConfigStruct.parity = USART_PARITY_NONE;
usartConfigStruct.stopBits = USART_STOP_BIT_1;
usartConfigStruct.wordLength = USART_WORD_LEN_8B;
usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
3.2.2 启用 CRC 外设时钟
在开始使用 CRC 前,需要先通过 RCC 外设启用 CRC 外设时钟。
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_CRC);
3.2.3 配置初始 CRC
CRC_CTRL 寄存器 RST 位置 1,配置初始 CRC 值寄存器(CRC_DATA) 将 CRC 数据寄存器设置为初始 CRC 0xFFFFFFF
CRC_ResetDATA();
3.2.4 CRC 数据校验
完成了开启时钟,初始值的配置后,调用 CRC 计算函数,利用 while 循环往数据寄存器里以 32 位为单位写入数据。当 BUFFER_SIZE 等于零时,意味着数据写入完毕,读取数据寄存器的值,得到的即为输出校验值。可以通过串口助手观察 到标准校验值和输出校验值,当输出校验值与标准校验值相等时,证明数据传输没有出错。
其中32 位数据(32bit Data)作为输入寄存器是写入时存储 CRC 计算器的 新数据。作为输出寄存器是读取时返回 CRC 计算的结果。
CRC_ResetDATA();
uCRCValue=CRC_CalculateBlockCRC((uint32_t*)aDataBuffer,BUFFER_SIZE);
printf("BlockCRC = 0x379E9F06 \r\n");
printf("CalculateBlockCRC = 0x%08X \r\n", uCRCValue);
CRC_CalcBlockCRC 函数代码如下:
uint_t CRC_CalculateBlockCRC(uint32_t *buf,uint32_t bufLen)
{
   While(bufLen--)
      {
         CRC->DATA = *buf++;
}
return (CRC->DATA);
}




使用特权

评论回复
沙发
1455555|  楼主 | 2023-7-24 10:47 | 只看该作者
帖子仅包含部分代码,具体参考APM32F4XX CRC例程,可去极海微官网进行下载使用

使用特权

评论回复
板凳
tpgf| | 2023-8-12 16:08 | 只看该作者
在不知情的前提下 如何知道使用的是哪个算式呢

使用特权

评论回复
地板
晓伍| | 2023-8-13 09:24 | 只看该作者
crc是自动添加的吗?还是说需要手动编写算法啊

使用特权

评论回复
5
八层楼| | 2023-8-13 09:49 | 只看该作者
同一个单片机其crc校验的算法是一样的吗

使用特权

评论回复
6
观海| | 2023-8-13 10:18 | 只看该作者
在进行校验的时候必须进行查表才可以吗

使用特权

评论回复
7
木木guainv| | 2023-8-13 10:45 | 只看该作者
为什么crc是非常经典的校验模型呢?为什么不会出现错误呢

使用特权

评论回复
8
guanjiaer| | 2023-8-13 17:00 | 只看该作者
正确的crc校验结果都是固定的数值吗

使用特权

评论回复
9
1455555|  楼主 | 2023-8-25 11:36 | 只看该作者
tpgf 发表于 2023-8-12 16:08
在不知情的前提下 如何知道使用的是哪个算式呢

我的理解是:如果是板载自带的CRC模块或者单独的硬件模块,通常手册上会标明。如果是自己写代码进行校验可以自行选择任意公式。

使用特权

评论回复
10
1455555|  楼主 | 2023-8-25 11:39 | 只看该作者
晓伍 发表于 2023-8-13 09:24
crc是自动添加的吗?还是说需要手动编写算法啊

我使用的是APM32F407的开发板 有板载硬件CRC 所以不需要我自己编写算法

使用特权

评论回复
11
1455555|  楼主 | 2023-8-30 15:17 | 只看该作者
本帖最后由 1455555 于 2023-8-30 15:28 编辑
观海 发表于 2023-8-13 10:18
在进行校验的时候必须进行查表才可以吗

帖子里用到开发板带有硬件CRC,就没有使用查表法,buf里面存的是需要传输的数据。如果使用纯软件CRC校验一般有查表法和按位校验法。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

17

帖子

1

粉丝