在数字信号的通信中,常常会因各种因素导致传输错误,于是,聪明的科学家以及开发人员便设计,研发出了各种防止传输错误的方法。校验码便是最常见的一种。
最常见的校验码是奇偶校验码,仅仅只占一位,便可以根据数据中0
或者1
的数量对数据提供校验;然而奇偶校验的缺点也很明显,首先,它对错误的检测概率大约只有50%
。也就是只有一半的错误它能够检测出来。另外,每传输一个字节都要附加一位校验位,对传输效率的影响很大(奇偶校验很简单,感兴趣的可以自己了解一下,不再赘述)。
奇偶校验优点也很明显,它很简单,因此可以用硬件来实现,这样可以减少软件的负担。
CRC(Cyclic Redundancy Check)循环冗余检验,是一种用于检测数据传输中出现错误的校验方法。其特征是信息字段和校验字段的长度可以任意选定。它通过生成一个循环冗余校验码,将校验码附加到待传输的数据中,接收方再根据相同的算法对收到的数据进行校验,如果校验码无误,则可以判定数据传输正确。
CRC校验可以有效地检测传输过程中可能发生的位错误、丢失数据或假包等问题,是一种常用的数据完整性保护方法。其优点是简单、高效,并且能够在较低的计算负载下提供较高的校验能力。
需要注意的是,CRC校验不能纠正错误,只能检测错误。在数据传输的场景中,如果发现数据传输存在错误,通常需要重新发送或采取其他的错误处理措施。
CRC能被广泛采用,肯定有其“过人之处”,让我们来看看它的庐山真面目。
发送方 给出需要传递的数据(Data),并定义多项式,以多项式得到(n+1)位除数(divisor),对数据的末尾补上n
位0
,作为被除数,用除数去除被除数,得到的余数就是所需要计算的n位CRC校验码,将得到的CRC校验码拼接到原始数据的末端生成新的数据,将这个数据一并传给接收方。
接收方 将得到的一整块数据作为被除数,用在发送方得到的除数去除被除数,如果结果余数为0
的话,代表数据的传输没有出错,得到的数据是正确且有效的。反之当前数据有误,将当前数据丢弃,并通知发送方重新发送。
还有另一种方法:发送方分别发送数据和CRC数据,结束方得到数据末尾补n
个0
作为被除数,用多项式除数去除被除数,得到的余数如果作为接收方的CRC校验码,如果接收方得到的CRC数据和发送方发的CRC一致的话,同样也可以证明数据的传输是没有问题的(本文采用第一种方法)。
CRC运算,也就是这种特殊的除法运算,必须要指定个除数,在CRC算法中,这个除数有一个专有名称叫做“生成多项式”。生成多项式的选取是个很有难度的问题,如果选的不好,那么检出错误的概率就会低很多。不过专家早已经考虑到了这个问题,给我们提供了好多个生成多项式可供选择。11001
便是其中之一(生成多项式的要求之一就是最高位和最低位必须为1
)。
假设我们现在需要传输一个8位二进制数据10110011
。我们选择除数为11001
,根据计算规则,在被除数后添加4
个0
。
可以看到,计算结果为100
,为了保证位数,在前面添加一个0
,变成了0100
,所以要发送的数据=原数据+CRC校验码,也就是101100110100
。
在接收方收到数据(其实是数据与CRC合并后的新数据)后,将其除以我们定义的除数,若结果为0
,则说明结果没错,反之当前数据有误,将当前数据丢弃,并通知发送方重新发送。计算过程如下。
从上述例子来看,余数为0
,说明数据传输没有问题。此时可对此次传输的数据做下一步处理,并准备接收新的数据。
模2除法与算术除法类似,但每一位除的结果不影响其它位。只需要自己简单模拟一遍便可知道。
分成4中情况:
数据A | 0 | 0 | 1 | 1 |
---|---|---|---|---|
数据B | 1 | 0 | 1 | 0 |
异或运算的结果 | 1 | 0 | 0 | 1 |
所以,我们可以得出结论,从结果上看,模2除法与异或运算是等同的。
这个问题并不难回答,这和除数,也就是生成多项式的特征有关系,在特征多项式中,最高位和最低位都为1
,而除法运算中,每次参与异或运算的两个数,最高位必然都为1
(“被减数”最高位为零则位数不够,必须向低位借数值),这样一来,运算的结果/中间结果最高位为0
,没有实际意义,所以余数最多也会比除数少1
位。
综上所述,CRC校验码不能纠正错误,只能检测错误。且一般情况下,用到CRC校验码的场景,通信速率都很高,所以在检出错误数据的时候,重新传输是一种简单便捷的方法。
CRC校验在CAN通信中用得比较多,对于确保数据传输的准确性起着非常重要的作用。
参考链接(均来自CSDN):