常用的数据校验方式(奇偶,CRC,异或校验, LRC校验,累加和,MD5等校验)概念及源码

数据校验概念

数据在传输的过程中,会受到各种干扰的影响,如脉冲干扰,随机噪声干扰和人为干扰等,这会使数据产生差错。为了能够控制传输过程的差错,通信系统必须采用有效的检错方案。因此产生了数据校验。

数据校验是为保证数据的完整性进行的一种验证操作。通常用一种指定的算法对原始数据计算出的一个校验值,接收方用同样的算法计算一次校验值,如果两次计算得到的检验值相同,则说明数据是完整的。

数据校验常见种类
最简单的检验
实现方法:最简单的校验就是把原始数据和待比较数据直接进行比较,看是否完全一样这种方法是最安全最准确的。同时也是效率最低的。
应用例子:龙珠cpu在线调试工具bbug.exe。它和龙珠cpu间通讯时,bbug发送一个字节cpu返回收到的字节,bbug确认是刚才发送字节后才继续发送下一个字节的。

奇偶校验
实现方法:根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验。采用奇数的称为奇校验,反之,称为偶校验。采用何种校验是事先规定好的。通常专门设置一个奇偶校验位,用它使这组代码中“1”的个数为奇数或偶数。若用奇校验,则当接收端收到这组代码时,校验“1”的个数是否为奇数,从而确定传输代码的正确性。
应用例子:单片机串口通讯有一模式就是8位数据通讯,另加第9位用于放校验值。

BCC异或校验法(Block Check Character)
实现方法:将数据按字节与校验码寄存器(寄存器初始值通常0))进行异或计数并存入校验码寄存器。
应用例子:IC卡接口通讯、很多单片机系统的串口通讯都使用。

CRC循环冗余校验(Cyclic Redundancy Check)
实现方法:这是利用除法(这里除法是模2除法也就是异或运算)及余数的原理来进行错误检测的.将接收到的码组进行除法运算,如果除尽,则说明传输无误;如果未除尽,则表明传输出现差错。CRC校验具还有自动纠错能力。CRC检验主要有计算法和查表法两种方法。
适用范围:CRC-12码通常用来传送6-bit字符串; CRC-16及CRC-CCITT码则用是来传送8-bit字符; CRC-32:硬盘数据,网络传输等。
应用例子:rar,以太网卡芯片、MPEG解码芯片中。

MD5校验和数字签名
实现方法:主要有MD5和DES算法。
适用范围:数据比较大或要求比较高的场合。如MD5用于大量数据、文件校验,des用于保密数据的校验(数字签名)等等。
应用例子:文件校验、银行系统的交易数据。


累加和检验(checksum)
实现方法:一组数据项的和。对溢出部分进行处理等到一个校验数值(8位,16位等)。累加和溢出各种方法有所差别。详见代码。
应用例子:数据通信领域等。

LRC校验(纵向冗余校验)(Longitudinal Redundancy Check)是一种从纵向通道上的特定比特串产生校验比特的错误检测方法。
实现方法:将每个字节数据求和结果与256求余,再按位取反加 1(256 - 余数)后即得到校验码
应用例子:在工业领域Modbus协议Ascii模式采用该算法

源码链接

BCC校验(异或校验),LRC校验(纵向冗余校验),累加和校验(CheckSum) 源码 链接:https://blog.csdn.net/weixin_46672094/article/details/117135918?spm=1001.2014.3001.5501

CRC校验 (计算方式) 通用源码(兼容CRC4/5/6/7/8/16/32/自定义) 链接:https://blog.csdn.net/weixin_46672094/article/details/117136044?spm=1001.2014.3001.5501

CRC校验 (查表方式) 通用源码(兼容CRC4/5/6/7/8/16/32/自定义),包含 CRC表 计算代码 链接:https://blog.csdn.net/weixin_46672094/article/details/117136086?spm=1001.2014.3001.5501

CRC计算原理被校验的数据 除以 多项式,得到的余数就是CRC数值。不过这里的除法是模2除法,也就是异或。多项式是通信中双方约定数,可以自己定义,不过目前有各个领域定义好的,可直接用。

以下以 数据 11001000(0xC8) 为例,演算CRC计算过程!

单个数据CRC计算过程:

数  据:11001000(0xC8)
多项式:10011(x4 + x + 1)(4位多项式) 多项式最高位总是1.

11001000 0000 //数据11001000(0xC8),4位多项式所以末尾补4个零
10011         //多项式
————————————————
 1010000 0000 //按位异或
 10011
————————————————
   11100 0000 //最高位是1才能除
   10011
————————————————
    1111 0000
    1001 1
————————————————
     110 1000
     100 11
————————————————
      10 0100
      10 011
————————————————
         0010 //余数 就是CRC值

通信中多数据CRC计算过程:其实就是把单数据的CRC最为下个数据CRC计算的初值下面还可以单个数据为例,多了CRC初值和一些数据的处理。

CRC5_EPC算法 逻辑演算过程:
	 
//CRC算法名称			宽度	多项式      初始值      结果异或值  输入反转    输出反转
{"CRC5_EPC", 			5, 		0x09,       0x09,       0x00,       E_FALSE,  	E_FALSE},

数据0 输入不反转             得到 数据1 : 0001 0011
数据1高位 与 CRC初始值异或   得到 数据2 : 0101 1011
0001 0011
0100 1      //初值与数据高位进行异或
————————————————
0101 1011
数据2 补CRC宽度数量的零 得到 数据3 : 0101 1011 00000
完整多项式: 1 01001 //高位异或始终为0,在计算可省了,下面为了展示原理过程加上的 1
数据3 与多项式模2除法(异或)计算  :
01011011 00000
 101001
————————————————
    1001 00000
    1010 01
————————————————
      11 01000
      10 1001
————————————————
       1 11010
       1 01001
————————————————
         10011
数据3 与多项式计算后     得到 余数0 :    1 0011
余数0 输出不反转         得到 余数1 :    1 0011
余数1 与结果异或值 异或  得到 CRC值 : 0001 0011 => 0x13
   1 0011
0000 0000 //与结果异或值 直接异或
————————————————
0001 0011




CRC5_USB算法 逻辑演算过程:

//CRC算法名称			宽度	多项式      初始值      结果异或值  输入反转    输出反转
{"CRC5_USB", 			5, 		0x05,       0x1F,       0x1F,       E_TRUE,   	E_TRUE},

数据0 输入反转          得到 数据1 : 1100 1000
数据1 与 初始值异或     得到 数据2 : 0011 0000
1100 1000
1111 1      //初值与数据高位进行异或
————————————————
0011 0000
数据2 补CRC宽度数量的零 得到 数据3 : 0011 0000 00000
完整多项式: 1 00101 //高位异或始终为0,在计算可省了,下面为了展示原理过程加上的 1
数据3 与多项式模2除法(异或)计算  :
00110000 00000
  100101
————————————————
   10101 00000
   10010 1
————————————————
     111 10000
     100 101
————————————————
      11 00100
      10 0101
————————————————
       1 01110
       1 00101
————————————————
         01011
数据3 与多项式计算后     得到 余数0 :    0 1011
余数0 输出要反转         得到 余数1 :    1 1010 //按位数宽度反转
余数1 与结果异或值 异或  得到 CRC值 : 0000 0101 => 0x05
   1 1010
0001 1111 //与结果异或值 直接异或
————————————————
0000 0101
CRC5_EPC算法 程序计算过程:

//CRC算法名称			宽度	多项式      初始值      结果异或值  输入反转  	输出反转
{"CRC5_EPC", 			5, 		0x09,       0x09,       0x00,       E_FALSE,  	E_FALSE},
data   =                            00010011(0x13)
with   = 5;
poly   = 00000000 00000000 00000000 00001001
crc    = 00000000 00000000 00000000 00001001
xorout = 00000000 00000000 00000000 00000000
refin  = E_FALSE
refout = E_FALSE

crc    = 00000000 00000000 00000000 01001000 //宽度小于8,右移8-5
poly   = 00000000 00000000 00000000 01001000 //宽度小于8,右移8-5

{
data   =                            00010011 //不移动
crc    = 00000000 00000000 00000000 01001000
—————————————————————————————————————————————
crc    = 00000000 00000000 00000000 01011011 //0,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00000000 10110110 //1,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00000001 01101100
poly   = 00000000 00000000 00000000 01001000 
—————————————————————————————————————————————
crc    = 00000000 00000000 00000001 00100100 //2,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00000010 01001000 //3,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00000100 10010000 //4,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00001001 00100000
poly   = 00000000 00000000 00000000 01001000 
—————————————————————————————————————————————
crc    = 00000000 00000000 00001001 01101000 //5,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00010010 11010000 //6,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00100101 10100000
poly   = 00000000 00000000 00000000 01001000 
—————————————————————————————————————————————
crc    = 00000000 00000000 00100101 11101000 //7,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 01001011 11010000
poly   = 00000000 00000000 00000000 01001000 
—————————————————————————————————————————————
crc    = 00000000 00000000 01001011 10011000
}

crc    = 00000000 00000000 00001001 01110011 //宽度小于8,右移8-5
                                       11111 //有效位 5
—————————————————————————————————————————————
crc    = 00000000 00000000 00000000 00010011





CRC5_USB算法 程序计算过程:

//CRC算法名称			宽度	多项式      初始值      结果异或值  输入反转  	输出反转
{"CRC5_USB", 			5, 		0x05,       0x1F,       0x1F,       E_TRUE,   	E_TRUE},

data   =                            00010011(0x13)
with   = 5;
poly   = 00000000 00000000 00000000 00000101
crc    = 00000000 00000000 00000000 00011111
xorout = 00000000 00000000 00000000 00011111
refin  = E_TRUE
refout = E_TRUE

crc    = 00000000 00000000 00000000 11111000 //宽度小于8,右移8-5
poly   = 00000000 00000000 00000000 00101000 //宽度小于8,右移8-5

{
data   =                            11001000 //输入反转 8位
    
data   =                            11001000 //不移动
crc    = 00000000 00000000 00000000 11111000
—————————————————————————————————————————————
crc    = 00000000 00000000 00000000 00110000 //0,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00000000 01100000 //1,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00000000 11000000 //2,crc & 0x80; 0-右移,1-右移后与多项式异或 
crc    = 00000000 00000000 00000001 10000000
poly   = 00000000 00000000 00000000 00101000
—————————————————————————————————————————————
crc    = 00000000 00000000 00000001 10101000 //3,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00000011 01010000
poly   = 00000000 00000000 00000000 00101000
—————————————————————————————————————————————
crc    = 00000000 00000000 00000011 01111000 //4,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00000110 11110000 //5,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00001101 11100000
poly   = 00000000 00000000 00000000 00101000
—————————————————————————————————————————————
crc    = 00000000 00000000 00001101 11001000 //6,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00011011 10010000
poly   = 00000000 00000000 00000000 00101000
—————————————————————————————————————————————
crc    = 00000000 00000000 00011011 10111000 //7,crc & 0x80; 0-右移,1-右移后与多项式异或
crc    = 00000000 00000000 00110111 01110000
poly   = 00000000 00000000 00000000 00101000
—————————————————————————————————————————————
crc    = 00000000 00000000 00110111 01011000
}

crc    = 00000000 00000000 00000110 111 01011 //宽度小于8,右移8-5
crc    = 00000000 00000000 00000110 111 11010 //输出反转 5位
xorout = 00000000 00000000 00000000 000 11111
—————————————————————————————————————————————
crc    = 00000000 00000000 00000110 111 00101
                                        11111 //有效位 5
—————————————————————————————————————————————
crc    = 00000000 00000000 00000000 000 00101

猜你喜欢

转载自blog.csdn.net/weixin_46672094/article/details/116753004