2023年12月7日发(作者:)

常用的数据校验方式(奇偶,CRC,异或校验,LRC校验,累

加和,MD5等校验)概念及源码

数据校验概念

数据在传输的过程中,会受到各种干扰的影响,如脉冲干扰,随机噪声干扰和人为干扰等,这会使数据产生差错。为了能够控制传输过程的

差错,通信系统必须采用有效的检错方案。因此产生了数据校验。

数据校验是为保证数据的完整性进行的一种验证操作。通常用一种指定的算法对原始数据计算出的一个校验值,接收方用同样的算法计算一

次校验值,如果两次计算得到的检验值相同,则说明数据是完整的。

数据校验常见种类

最简单的检验

实现方法:最简单的校验就是把原始数据和待比较数据直接进行比较,看是否完全一样这种方法是最安全最准确的。同时也是效率最低的。

应用例子:龙珠cpu在线调试工具。它和龙珠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模式采用该算法

源码链接

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 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

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