据说刚过去的高考数学很难,小编当年上学时挺喜欢数学的,最近特意复习了一下crc校验的计算过程。
crc是众多校验方式中的一种,校验的目的是为了检测数据的正确性。在详细介绍crc计算之前,我们先来看两个常见的较为简单点的校验:串口通信中的奇偶校验和身份证号码中的mod 11-2校验。
先看奇偶校验,假设要发送8位数据10110101,奇校验是再加一位校验位,让这9位数据中的1的个数为奇数。
10110101->101101010 奇校验
偶校验是让这9位数据中1的个数为偶数。
10110101->101101011 偶校验
接收方收到数据后计算其奇偶性,如果不对,则说明数据传输中发生了错误。
奇偶校验优点是使用简单,缺点是检错率有限,只有奇数个数据位发生变化的错误能检测到,偶数个数据位变化的错误它检测不了。
最近拿着身份证去核酸检测的次数太多了,让我对身份证号码的组成产生了兴趣,尤其好奇的是为什么有的身份号号码最后一位是x。身份证号码总共18位,包括17位数字码和1位校验码。
1)1-6位是地址码,表示编码对象所在县。
2)7-14位是出生日期码,表示编码对象出生的年、月、日。
3)15-17位是顺序码,表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
4)校验码,用来检验身份证号码是否正确,采用mod 11-2校验码系统。
校验的公式如下:
简单来说它的校验规则是:连校验码一起,由从右到左逐位乘以2的n次方取模11并求和,对11的余数必须为1。
以一个身份证号码11010519491231002x为例,
校验码计算如下:
1) 将前面的身份证号码17位数分别乘以不同的系数。从左到右的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
2) 将这17位数字和对应的系数各自相乘的结果相加7+9+0+5+0+20+2+9+24+27+7+18+30+5+0+0+4=167;
3) 用加出来的和167除以11,余数是2;
4) 余数2对应校验码是x;
看完上述计算方法之后,大家可以用自己的身份证号码试试。
该校验算法据说可以:
1) 如果某一位填错了,则校验算法可以检测出来。
2) 如果身份证号的相邻2位填反了,则校验算法可以检测出来。
这也是为什么要除以11而不是10的原因,其背后的数据理论推理已经超出了我的能力范畴,这里不再介绍了。
上面的两种校验和crc校验没有什么关系,只是为了让大家对校验先有个感性的认识,下面来正式介绍crc。
我在网上找了两个计算crc的软件,输入同样的数据,选择同样的算法,得到的结果一样,
这两个软件的对应关系如下:
把crc calculator info 中的这几个参数弄明白,crc的过程你也就清楚了
name:算法的名称,比如对于16bit的crc来说就有好多个名字,也就是虽然都是16 bit crc,但是计算方式也有好多种。
width:指的crc校验值的长度,通常有8bit,16bit,24bit,32bit等。
poly:是多项式的值,以上面图中的crc-8:x8+x2+x+1为例,它表示二进制为100000111,去掉最高位的1,十六进制表示就是0x07
init: init 的位数和poly的位数相同,它的值为全0或者全f,当全为0时,在算法开始前对数据(这个数据是根据refin的值得到的)后面补上crc位数个0后就可以进行后续计算了。当全为1时,表示在算法开始前对数据的前crc位数(高位)先和对应位数个1进行异或(即:前crc位数的值按位取反),再在后面补上crc位数个0,才进行后续计算。
refin和refout:它们要么全为false,要么全为true。
refin为false表示,输入的原始数据的每个字节的第7位作为最高有效位,第0位作为最低有效位,即正常计算即可
当refin为true时,输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据,以一个4字节的原始数据为例:
当refout为false时,输出不做处理,当refout为true,需要对输出数据做一次整个数据的逆序处理,注意:这里做的逆序和refin不同,它不是按字节逆序,而是整个逆序,以crc-32为例来说明,最后的数据为32位,当refout为true时,翻转如下:
xorout:表示根据上面参数计算完后,和这个数再进行一次异或。
下面分析一下上面的结果0x79的由来:
1) 0x13 对应二进制为00010011
2) 由于refin为false,所以0x13不做处理还是00010011
3) 因为init为0x00,00010011后面加8个0即可,输入数据变为0001001100000000
4) 多项式为x8+x2+x+1 对应二进制100000111,将上述0001001100000000 除以该多项式对应的100000111
整个计算过程如下:
最后得到余数:01111001
5) 由于refout为false,所以余数不变,还为01111001
6) 由于xorout为0,表示不用再取反,所以最终的结果就是01111001,即十六进制0x79
算一个不过瘾,我们再来计算一个
这一次和上面唯一的不同是将初始值由原来的0x00换为了0xff,这个例子就是给大家演示初始值到底什么意思.
下面分析一下上面的结果0x79的由来:
1) 0x13 对应二进制为00010011
2) 由于refin为false,所以0x13不做处理还是00010011
3) 因为init为0xff,00010011的高8位要先与0xff异或,输入数据变为11101100,后面再加入8个0,变为 1110110000000000
4) 多项式为x8+x2+x+1 对应二进制100000111,将上述1110110000000000 除以该多项式对应的100000111,最后得到余数:10001010
5) 由于refout为false,所以余数不变,还为10001010
6) 由于xorout为0,表示不用再取反,所以最终的结果就是10001010,即十六进制0x8a
这个例子演示了初始值的含义,我们再看最后一个例子,这个例子演示了refin和refout为true的具体含义
1) 0x13 对应二进制为00010011
2) 由于refin为true,所以0x13需要逆序一下得到11001000
3) 因为init为0x00,所以11001000后面直接添加4个0即可,得到110010000000
4) 多项式为x4+x+1 对应二进制10011,将上述110010000000 除以10011,最后得到余数:0010
5) 由于refout为true,所以余数要逆序变为0100
6) 由于xorout为0,表示不用再取反,所以最终的结果就是0100
crc每种参数模型的检错能力,同时crc也可以纠错,这需要专业的数学计算,这也超出了我的能力,这里也不介绍了。
看完这些大家应该都清楚了crc的计算,有些 mcu本身集成了硬件crc模块,你只需要配置寄存器,就可以算出crc结果了,或者也可以通过软件来实现,https://github.com/whik/crc-lib-c 有一个开源的代码可以用。不管哪种方法,了解下详细的计算过程还是有好处的。
crc计算软件和github 软件代码下载如下:
https://cowtransfer.com/s/05d6adadea654c 或 打开【奶牛快传】cowtransfer.com 使用传输口令:diz36q 提取
RTU在环境监测领域的应用
惠普实验室发明首台忆阻器激光器
无人机无线视频传输的应用挑战
华为起诉三星专利侵权,要求停止侵权并索赔千万
智慧停车市场即将爆发了吗
CRC校验的计算过程
基于PCI-9846H的死区时间引起的电压波形畸变的研究
深度学习走进了一个死胡同?
华为历经十多年,接入网终于突破日韩市场
SONY图像传感器IMX390CQV的特点
第五届深圳教育装备博览会圆满结束,展示数字化教育发展新动能!
将数据转换器IP集成到系统芯片简化设计技术
多路复用数据采集系统构成和应用面临的挑战
NAVEE S65电动滑板车在海外indiegogo正式开启众筹
安全关键应用中异构臂核心的软件注意事项
直线电机在可折叠OLED屏幕上的应用
1.6亿购国轩高科20%股权 佛山照明进军新能源电池
视频会议系统会议室装修注意事项
Tensilica 处理器在90纳米工艺速度500MHz
5G智慧政务应用实例