以前在嵌入式开发中进行CRC校验一般通过软件算法实现,TM4C1294自带CRC校验单元,但坑比较多,发出来供使用时参考
CRC单元只有一个寄存器,7个字段需要配置
INIT:初始值;
SIZE: 选择校验数据是8位还是32位;
RESINV:输出按位取反;
OBR:输出字节反转,例如B0[7:0]-->B0[0:7]
BR:输入字节反转,例如B0[7:0]-->B0[0:7]
ENDIAN:大小端控制
TYPE:校验类型,即选择生成多项式
看着简单,发现不了解CRC校验算法还是一脸懵逼
那简单了解下CRC算法,首先CRC校验算法有很多种,根据生成校验数据位数的多少分为CRC-8、CRC-16、CRC-32等很多种,在嵌入式里面最常用的是CRC-16这种,但CRC-16根据生成多项的不同又分为几种,最常用的两种也是TM4C1924支持的两种是
CRC-16/CCITT : 生成多项式是0x1021
CRC-16/MODBUS:生成多项式是0x8005
而这两种之中最最常用的就是CRC-16/MODBUS,下面以此为例讲下寄存器该如何配置
到现在知道了TYPE和SIZE该怎么配置,再加上单个字节数据校验不存在大小端的问题,ENDIAN也知道怎么配置了,但还有几个关键寄存器不知道,难道真的要把CRC算法了解一遍,也有简便的方法,实用软件CRC Caculator,下载链接在此https://download.youkuaiyun.com/download/crazin/10670926
在这个软件里面,选择不同的的CRC校验算法右侧有该算法的相关信息,例如CRC-16/MODBUS的信息如下
跟上面配置寄存器是对应的
Init:0XFFFF 对应初始值是全1,即初始值寄存器INIT应该设置为0x3;
RefOut:True,对应输出字节反转,即OBR=1;
RefIn:True,对应输入字节反转,即BR=1;
XorOut:0x0000,对应输出保持不变不按位取反,即RESINV=0;
CRC-16/MODBUS的配置寄存器应配置如下:
HWREG(CCM0_BASE+CCM_O_CRCCTRL)=0x7180;
//INIT = 0x3; 初始值 0XFF
//SIZE = 1; 8bit
//RESINV =0; 输出异或值0X0000
//OBR =1; RefOut 输出按字节反转,例如B0[7:0]-->B0[0:7]
//BR =1; RefIn 输入按字节反转,
//ENDIAN = 0;
//TYPE = 0; Polynomial 0x8005
CRC校验直接调用官方提供的驱动函数CRCDataProcess即可搞定。
其实还有一点问题,校验完未按进行按位反转的结果是放在CRC SEED里面的,按位反转后的结果是放在 CRC Post Processing Result 里面的(CRC-16/MODBUS结果因未按位取反,故结果两个寄存器结果一致)
之所以这样是方面进行连续校验,比如你要校验20个字节,你可以先校验10个字节,然后用存在CRC SEED里面的校验结果再与后面十个字节进行校验。
需要注意的是CRC单元默认是要进行连续校验的,因为虽然在初始化的时候把INIT设置为了1,但INIT是会自动清零的,也即往CRCDIN 里面出入第一个要校验的字节之后INIT就会自清零,下次将使用CRC SEED的值作为初始值,这也是CRC校验算法的基本流程,对第一个字节做校验,将校验结果作为初始值在对第二个字节进行校验。
所以正确的校验程序应该在每次开始校验前对INIT重新赋值或者对CRC SEED写为0xFFFF;
常用CRC-32的校验信息如下:
对应的CRC-32的配置寄存器应配置如下:
HWREG(CCM0_BASE+CCM_O_CRCCTRL)=0x63b2;
//INIT = 0x3; 初始值 0XFFFFFFFF
//SIZE = 0; 32bit
//RESINV =1; 输出异或值0XFFFFFFFF
//OBR =1; RefOut 输出按字节反转,例如B0[7:0]-->B0[0:7]
//BR =1; RefIn 输入按字节反转,
//ENDIAN = 0x03;
//TYPE = 0X2; Polynomial 0x4C11DB7