CRC校验怎么算?
据说刚过去的高考数学很难,小编当年上学时挺喜欢数学的,最近特意复习了一下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
本文转载自公众号玩点嵌入式,版权归原作者所有,不代表本站观点,如有侵权请与本站联系,本站将第一时间删除
- 分享
- 举报
-
浏览量:1458次2019-06-20 11:31:03
-
浏览量:1323次2023-11-23 14:38:15
-
浏览量:6700次2022-02-19 16:25:21
-
浏览量:2778次2023-12-25 14:11:19
-
浏览量:5108次2022-07-21 14:02:50
-
浏览量:851次2022-09-03 09:00:55
-
浏览量:1411次2023-07-11 12:40:32
-
浏览量:1872次2018-05-16 15:09:09
-
浏览量:45945次2019-07-25 11:31:42
-
浏览量:1573次2018-12-19 09:58:01
-
浏览量:2226次2020-08-28 15:08:37
-
浏览量:586次2023-06-13 17:36:39
-
浏览量:736次2023-12-06 16:50:25
-
浏览量:5326次2023-03-06 19:55:34
-
浏览量:2133次2019-07-02 09:48:10
-
浏览量:1735次2019-07-11 15:58:25
-
浏览量:2443次2020-08-06 15:36:48
-
2022-10-21 14:52:47
-
浏览量:555次2023-11-20 15:10:32
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
IPC摄像机
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明