|
路线栈欢迎您!
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
前言
数据传输中经常听到CRC效验,一个完整的数据帧通常由以下部分构成:帧头+数据+校验位+帧尾
校验位是为了保证数据在传输过程中的完整性,采用一种指定的算法对原始数据进行计算,得出的一个校验值。接收方接收到数据时,采用同样的校验算法对原始数据进行计算,如果计算结果和接收到的校验值一致,说明数据校验正确,这一帧数据可以使用,如果不一致,说明传输过程中出现了差错,这一帧数据丢弃,请求重发。
常用的校验算法有奇偶校验、校验和、CRC,还有LRC、BCC等不常用的校验算法。
以串口通讯中的奇校验为例,如果数据中1的个数为奇数,则奇校验位0,否则为1。
例如原始数据为:0001 0011,数据中1的个数(或各位相加)为3,所以奇校验位为0。这种校验方法很简单,但这种校验方法有很大的误码率。假设由于传输过程中的干扰,接收端接收到的数据是0010 0011,通过奇校验运算,得到奇校验位的值为0,虽然校验通过,但是数据已经发生了错误。
校验和同理也会有类似的错误:
一个好的校验校验方法,配合数字信号编码方式,如(差分)曼彻斯特编码,(不)归零码等对数据进行编码,可大大提高通信的健壮性和稳定性。例如以太网中使用的是CRC-32校验,曼彻斯特编码方式。
RC 算法(模二计算)
CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数除以另一个数。得到的余数作为校验数据附加到原数据后面。
模二计算本质上就是异或运算,相同的位为0,不同的位为1,也就是不考虑进位、错位的二进制加减法运算,例如:10011011 + 11001010 = 01010001.
接收方接收此数据后,再做除数运算,余数应该为0。
1.宽度(Width): 指CRC校验码的宽度,同时也是指多项式的宽度。
crc16的width是16,crc32的宽度是32。
2.多项式(Poly):指CRC校验的多项式的二进制码去掉最高位。
crc8的Poly:gx=x8+x2+x1+1,二进制码100000111,去掉最高位所以POLY这个参数为:0x07
3.初始值(Init),是指CRC的寄存器的初始值。
4.输入值反转(RefIN):是指需要校验的数据(输入值)二进制位数相反。
输入值为:10101100,则实际进行校验的值为00110101。
5.输出值反转(RefOut):指输出的校验码二进制位进行反转。
输出值为:10101100,则实际输出值为00110101。
6.结果异或值(XorOut): 指运算出的校验码与结果异或值异或之后,最终最为校验码。
XorOut为0xff,计算的校验码为0x17,则输出校验码为:0xff^0x17。
规定:生成多项式对应的二进制位数 比 CRC校验码的宽度多一位。
CRC校验的流程
1.选定一个标准除数(二进制数据)。
2.在要发送的数据后面加上冗余校验码的宽度位0,然后将这个新数 以模2除法的方式除以上面这个标准除数,所得到的余数也就是该数据的CRC校验码。
(注:余数必须比除数少且只少一位,不够就补0)
3.将这个校验码附在 被除数 后面,构成新的数据,发送给接收端。
4.接收端将接收到的数据 除以标准除数,如果余数为0则认为数据正确。
(1). 只有当位串的最高位为1,我们才将它与poly做XOR运算,否则我们只是将位串左移一位。
(2). 异或运算的结果实质上是被操作位串与poly位长-1的各位进行运算的结果,因为最高位总为0。
因为除数和被除数第一位必定是1 异或之后就是0
代码
- #define POLY 0x1021
- /**
- * @param: addr: 存放数据的数组地址
- * lenth: 数组长度
- * crc: crc初始化的值
- */
- uint16_t crc16(unsigned char *addr, int lenth, uint16_t crc)
- {
- int i;
- for (; lenth> 0; lenth--) // 数组有多少字节进行多少次计算
- {
- crc = crc ^ (*addr++ << 8); //先算第一个字节
- for (i = 0; i < 8; i++)
- {
- if (crc & 0x8000)
- crc = (crc << 1) ^ POLY;
- else
- crc <<= 1;
- }
- crc &= 0xFFFF; // 确保出来的CRC是16位,多余的清零
- }
- return crc;<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码
通用CRC表
- 芯片DS2401/DS18B20,都是使用的CRC-8/MAXIM模型
- SD卡或MMC使用的是CRC-7/MMC模型
- Modbus通信使用的是CRC-16/MODBUS参数模型
- USB协议中使用的CRC-5/USB和CRC-16/USB模型
- 很多ARM芯片带硬件CRC计算模块使用的是CRC-32模型
结语
CRC校验并不能100%的检查出数据的错误,非常低的概率会出现CRC校验正确但数据中有错误位的情况。这和CRC的位数,多项式的选择等等有很大的关系,所以在实际使用中尽量选择标准CRC参数模型,这些多项式参数都是经过理论计算得出的,可以提高CRC的检错能力。更多相关内容请看:常用的crc16标准校验算法和C代码,HC32F4A0 CRC32校验。
|
|