介绍
-
CRC用于解决什么问题?
CRC是一个数据验证单元,可以用于验证flash中的程序,传送的tcp,udp>数据包,串口传送的modbus信息。保证这些信息在传送过程中没有丢失,或者发生错误。 -
CRC怎么工作的啦? 我的理解是这样的。CRC使用时必然伴随一个数据发送端和一个数据接收>端。发送端通过软件或者支持CRC计算的硬件单元,计算出要发送数据的CRC校验值。再将这个检验值添加到要发送数据的结尾,一起发送给接收端。 接收端接收到完整的数据后,对数据以同样的方法进行CRC计算。这个时>候计算就不只有数据,还包括添加进来的CRC校验值。如果最后检验出的>结果为0,表示数据传输没有问题,如果校验结果不是0,那就表示数据有问题。对于flash中的程序也是同样的思路。
-
CRC如何计算数据的校验值啦? 说到这里就需要了解一些CRC的基本概念了。
## CRC基本概念
1. 待校验数据: 这个简单就是我们的原料,比如我们要传递的数据,flash中的程序,要传递的TCP,UDP包 -
CRC多项式: 这个多项式非常重要,它是CRC校验的关键。不论你是准>备使用软件实现CRC校验值计算,还是使用MCU,SOC提供的硬件单元实现CRC计算。都需要有这么一个多项式,它就是我们计算规则的代表。随便打>开一个CRC在线计算的网站,都会给出不同位数,不同CRC检验方式的多项式形式。最常用的是32位和16位的,其中32位是使用最多的,因为网络就是基于32位多项式。读者可以自行搜索多项式的表达方式,以及计算过程。
-
输入位宽: 其实多项式就已经决定了CRC检验结果的位数。那为啥还要有一个输入位宽拉?输入位宽可以让你将一个32位或16位宽的数据,分成8位宽的数据,依次进行CRC计算。比如一个0x12345678的32位数据可以分解为4个8位数据,0x12,0x34,0x56,0x78分别计算。一般高位在前。
-
输入输出反转: 输入的数据和输出的数据可以进行反转。这里的反转>不是0变1,而是最高位变成最低位,次高位变成次地位。比如0x01反转后就是0x80。
-
输入初始值: 就是在计算开始前CRC的值。一般是0xFFFFFFFF
-
输出异或值: 就是计算完成后还要和这个数进行异或。异或运算是C中
一个运算符号,相同为0,不同为1。一般为0xFFFFFFFF或者0x00000000 -
CRC模式: 就是对上面的各种参数进行组合。比如CRC32模式就是,多>项式为:0x4C11DB7,输入位宽: 可以8,16,32不影响只是数据组织方式>不同,输入输出都反转,输入初始值:0xFFFFFFFF,输出异或值0xFFFFFFFF。更多的CRC模式可以找一个CRC在线计算的网站,一般都会有比较详细>的介绍。
具体使用
st32的介绍说全系列都支持32位多项式。一般32位多项式都是0x4C11DB7>,方便兼容网络协议。一些国产芯片同时还支持8,16,32位数据输入,16位多项式,数据反转的不同的功能。本人感觉对于多数MCU来说16位CRC>比较适用,对于uart本就不快的速度每个数据祯后加4位CRC验证数据还是有点奢侈。很多成熟的协议比如CAN也都采用16位CRC。再说下为啥芯片里面要集成硬件CRC,因为计算快,如果没有硬件CRC,如果非要使用CRC验>证就只能软件模拟。计算过程全是用for循环一位一位计算,对于MCU本就稀缺的计算资源更是一种极大消耗。很多国产MCU还会集成除法硬件单元>,就是为了给软件提取。
实际例子
软件模拟CRC计算过程我就不献丑了,网络上也有很多,唯一遗憾的是多>
是一些零星的算法,要想比较全面了解可以找一些别人实现的库,应该就比较全面的包括了各种多项式的各种CRC算法了。这里只是简单的列举一>下在MCU中的使用。
unsigned char data_send[8] = {0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21};
unsigned char data_receive[12] = {0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21, 0xC1, 0x5A, 0x14, 0x7D};
volatile unsigned int crc_value;
crc_init();
crc_set_mode(CRC32_MPEG_2);
crc_set_bit_wide(CRC_WIDE_8);
crc_set_rst_bit();
crc_value = get_crc(data_send, 8); /* 0xC15A147D */
crc_value = get_crc(data_receive, 12); /* 0x00000000 */
开始的初始化,设置模式,设置输入位宽不同的MCU方法不同。不同的MCU
支持的多项式也不同,但一般32位的0x4C11DB8还是支持的,只是可能不>支持CRC32_MPEG_2
模式。读者可以上CRC在线计算网站计算需要模式CRC值。然后就是计算0x12345678和0x87654321的CRC校验值。再下一行就是>计算加入CRC检验值后的CRC值,计算出来应该为0。要是不为0多半你程序错了。 ~