热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

常用校验算法

1、在计算机通信中为什么需要对接收的数据进行校验?在计算机通信中,可能是点对点通信或者是广播方式通信,具有发送端设备和接收端设备。在整个通信网络或通信线路里面,存在有该设备需要的数据、

1、在计算机通信中为什么需要对接收的数据进行校验?

        在计算机通信中,可能是点对点通信或者是广播方式通信,具有发送端设备和接收端设备。在整个通信网络或通信线路里面,存在有该设备需要的数据、其他设备需要的数据、干扰所产生的信号(如果不处理,可能也会被当成正常数据进行处理)。同时,由于接地不好或者干扰源的问题(例如电焊机、变频器、中频炉等),可能使部分数据被干扰,数据不完整或者错误。如果这些错误或不完整的数据被执行,就可能使设备产生误动作,造成设备损坏、生产损失,甚至人身伤害。因此,就需要对这些数据进行处理,进行校验。
2、有哪几种校验方法?并简述各种校验的实现方法? 
      正好以前我自己发过这样的贴(原创),我摘抄过来。

原创:数据帧校验总结(CRC_LRC_PC_SC_S-XORC校验等):http://www.gongkong.com/webpage/forum/200810/2008101411312700003-1.shtml

冗余校验: 
      在通讯时采取数据校验的一种办法。数据传输时,虽然数据的起始字符和结束字符可以避免参与通信的设备收到无用的数据信息/干扰信息,但对于起始字符和结束字符之间的数据,还是可能受到干扰而产生错误,因此对通信数据进行校验是非常必要的。校验的方法是在数据的最后加上一个冗余信息,这个信息是对数据校验的结果,所以数据校验也称之为冗余校验。循环冗余码校验是最常用的校验方法之一。

差错检测和纠正:

       物理过程所引起的差错,在某些介质中通常是突发的而不是单个的。网络设计者已经研究出两种基本的策略来处理差错。一种方法是在每一个要发送的数据块上附加足够的冗余信息,使接收方能够推导出已发出的字符应该是什么。另一种方法是只加足够的冗余位,使接收方知道差错发生,但不知道是什么样的差错,然后要求接收方重新进行传输。前者的策略是使用纠错码(error-correcting code),而后者则使用检错码(error-detecting code)。 
1.纠错码

       在了解纠错码之前,先了解一个基本概念:海明距离。通常一帧包括m个数据(报文)位和r个冗余位或者校验位。设整个长度为n(即n=m+r),则此长度为n的单元通常被称作n位码字(codeword)。 
给出任意两个码字,如10001001和10110001,可以确定它们有多少个对应位不同。在此例中有3位不同。为了确定有多少位不同,只须对两个码字做异或运算,然后计算结果中1的个数。两个码字中不同位的个数,称为海明距离(Hamming Distance)。其重要性在于,假如两个码字具有海明距离d,则需要d个位差错才能将其中一个码字转换成另一个。

      一种编码的校验和纠错能力取决于它的海明距离。为检测出d比特错,需要使用d+1的编码;因为d个单比特错决不可能将一个有效的码字转变成另一个有效的码字。当接收方看到无效的码字,它纠能明白发生传输错误。同样,为了纠正d比特错,必须使用距离为2d+1的编码,这是因为有效码字的距离远到即使发生d个变化,这个发生了变化的码字仍然比其它码字都接近原始码字。作为纠错码的一个简单例子,考虑如下只有4个有效码字的代码: 
0000000000、0000011111、1111100000和1111111111

      这种代码的距离为5,也就是说,它能纠正双比特错。假如码字0000000111到达后,接收方知道原始码字应该为0000011111。但是,如果出现了三位错,而将0000000000变成了0000000111,则差错将不能正确地纠正。

2.检错码

      检错码有时也用于数据传输。例如,当信道为单工方式,无法要求重传的情况下,大多数采用检错码加重传的方式。 
假设信道的出错是孤立的,信道的误码率为每位10-6。数据块的大小为100位。为1000位的数据块纠错,需要10个校验位;1兆的数据位将需要10000个校验位。若只需要检测一个数据块的一位错误,每块一个奇偶位就够了。每传送1000个数据块就需要额外传送一个数据块。错误检错+重传方式的整个开销,仅仅是每兆数据只有2001位,而海明码为10000位。

      假若在一个块上只加一个奇偶位,那么块的长的突发错误的检测率就会很糟糕,能够检测到差错的概率只有0.5,这是难以接受的。改进的措施可以采取将每个数据块组成n位宽k行高的长方形矩阵进行发送。对每一列的奇偶位分别进行计算,附加在矩阵上,作为矩阵的最后一行,然后按行进行发送。当块到达后,接收方检测所有的奇偶位。如果其中任何一个出错了,就需要重新传送整个块。

      这种方法能够检测到单个程度为n的突发错误,因为每一列只有一位改变了。然而如果第一位变反,最后一位变反,且所有其它位都正确,则长度为n+1的突发差错将不会被检测到。假如一个块被一个长的突发差错或者短的突发差错所破坏,n列中的每一列的奇偶值碰巧正确的概率为0.5,那么这个出错块被接受的概率不应该是2-n。

      虽然上述方法有时已经足够了,但是在实践中,另一种方法正在被广泛使用,即多项式编码(也叫循环冗余码,或CRC码)。多项式编码是基于将位串看成是系数为0或1的多项式,一个k位帧可以看成是从Xk-1到X0的k-1次多项式的系数序列。如果采用多项式编码的方式,发送方和接收方必须事先商定一个生成多项式G(x),生成多项式的高位和低位必须是1。要计算m位的帧M(x)的校验和,生成多项式必须比该多项式短。基本思想是:将校验和加在帧的末尾,使这个带校验和的帧的多项式能被G(x)除尽。当接收方收到带校验和的帧时,用G(x)去除它,如果有余数,则传输出错。 
计算校验和的算法如下: 
①.设G(x)为r阶,在帧的末尾附加r个零,使帧为m+r位,则相应的多项式是XrM(x)。 
②.按模2除法用对应于G(x)的位串去除对应于XrM(x)的位串。 
③.按模2减法从对应于XrM(x)的位串中减去余数。结果就是要传送带校验和的帧,叫多项式T(x)。 
以下三个多项式已经成为国际标准: 
crc -12 = x^12+x^11+x^3+x^2+x+1 
crc -16 = x^16+x^15+x^2+1 
crc -ccitt = x^16+x^12+x^5+1

      这三个多项式都包含了x+1作为基本因子。当字符串长度为6位时,使用CRC-12;其余两个多项式用在字符串长度为8位的情况下。一个16位的校验和,如CRC-16或CRC-CCITT,可以捕捉到所有的单位差错和双位差错,所有奇数位数的差错,所有长度小于或等于16位的突发差错,99.997%的长度为17位的突发差错,以及99.998%的长度为18位或多于18位的突发差错。

      虽然计算校验和的计算方法看起来相当复杂,但Peterson和Brown已经给出了一种简单的移位寄存器电路来进行计算,并用硬件来完成对校验和的校验。在实际应用中,几乎都在使用此硬件。

一、CRC循环冗余校验

CRC:Cyclical Redundancy Check,循环冗余校验,简称CRC校验。 
下面以实例对这种校验方法做个说明。 
台达VFD-M系列变频器的Modbus RTU模式採用CRC偵誤值,CRC偵誤值以下列步驟計算: 
步驟1:載入一個內容為FFFFH之16-bit寄存器 (稱為CRC寄存器)。 
步驟2:將命令訊息第一個位元組與16-bit CRC寄存器的低次位元組進行Exclusive OR運算(异或运算),並將結果存回CRC 寄存器。 
步驟3:將CRC寄存器之內容向右移1 bit,最左bit填入0,檢查CRC寄存器最低位元的值。 
步驟4:若CRC寄存器的最低位元為0,則重覆步驟3;否則將CRC寄存器與A001H進行Exclusive OR運算。
步驟5:重覆步驟3及步驟4,直到CRC寄存器之內容已被右移了8 bits。此時,該位元組已完成處理。 
步驟6:對命令訊息下一個位元組重覆重覆步驟2至步驟5,直到所有位元組皆完成處理,CRC寄存器的最後內容即是CRC值。當在命令訊息中傳遞CRC值時,低位元組須與高位元組交換順序,亦即,低位元組將先被傳送。 
例如,從地址為01H之交流電機驅動器的2102H地址讀取2個字,從ADR至資料數之最後一位元組所計算出之CRC寄存器之最後內容為F76FH,則其命令訊息如下所示,其中6FH於F7H之前傳送。 
命令訊息 
ADR 01H 
CMD 03H 
啟始資料地址 21H 
02H 
資料數(以word 計算) 00H 
02H 
CRC CHK Low 6FH 
CRC CHK High F7H 

下例乃以C語言產生CRC值。此函數(function)需要兩個參數:Unsigned char* data:指向訊息緩衝區(buffer)之指標;Unsigned char length:訊息緩衝區中之位元組數目;此函數將傳回unsigned integer型態之CRC值。 
unsigned int crc_chk(unsigned char* data, unsigned char length){ 
int j; 
unsigned int reg_crc=0xFFFF; 
while(length--){ 
reg_crc ^= *data++; 
for(j=0;j<8;j++){ 
if(reg_crc & 0x01){ /* LSB(b0)=1 */ 
reg_crc=(reg_crc>>1) ^ 0xA001; 
}else{ 
reg_crc=reg_crc >>1; 



return reg_crc; 
}

 

由于计算CRC校验值比较麻烦,我们可以利用现成的软件进行计算。这样的软件有很多,例如:

 

二、LRC纵向冗余校验

LRC:Longitudinal Redundancy Check,纵向冗余校验,简称LRC校验或纵向校验。 
      下面以实例对这种校验方法做个说明。 
      台达VFD-M系列变频器的Modbus ASCII通信模式採用LRC偵誤值。LRC偵誤值乃是將ADR1至最後一個資料內容加總,得到之結果以十进制的256為單位,超出之部分去除(例如得到之結果為十六進位之128H則只取28H(减去了100H,就是减去了256D)),然後計算二次反補後得到之結果即為LRC偵誤值。例如:從地址為01H之交流電機驅動器的0401H地址讀取1個字。 
STX ‘:’ 
ADR 1 ‘0’ 
ADR 0 ‘1’ 
CMD 1 ‘0’ 
CMD 0 ‘3’ 
啟始資料地址‘0’ 
‘4’ 
‘0’ 
‘1’ 
資料數 ‘0’ 
‘0’ 
‘0’ 
‘1’ 
LRC CHK 1 ‘F’ 
LRC CHK 0 ‘6’ 
END 1 CR 
END 0 LF 
01H+03H+04H+01H+00H+01H=0AH, 0AH的二次反補為F6H。 

二次反补:取反然后加1B或1H(1B=1H)。 
计算方法1: 
取反后加1B:把数据转换为二进制,每位取反后再加1B。例如:0AH=00001010B,按位取反后得11110101B,11110101B+1B=11110110B=F6H,0AH的二次反补就是F6H。 
取反后加1H:把数据转换为二进制,每位取反后再加1H。例如:0AH=00001010B,按位取反后得11110101B=F5H,F5H+1H=F6H,0AH的二次反补就是F6H。 

计算方法2: 
有个简单算法就是:这个十六进制值有几位数,就把高于这个位数的最小值减去这个值。如果16进制数有2位,那么高于2位的最小值就是100H,用100H减去这个数就是其二次反补。 
      实际上,该方法的原理和方法1相同:以2位16进制数为例,FFH减去那个数就是把那个数取反(FFH的数据为全1,减去那个数的结果就是原来1的位数变为0,原来0的位数变为1),而FFH+1H=100H。所以取反然后加一就等于100H减去这个数。 
      例如:0AH的二次反补就是:100H-0AH=F6H

三、PC奇偶效验

      奇偶校验:Parity Check,是检测数据完整性的一种方法,一种冗余校验。通过该校验将重新计算的奇偶校验位与预先给出的奇偶校验位进行比较,测试二进制数字阵列中数字1(或0)的数目是奇数还是偶数的一种检查。这种校验设置一个奇偶校验位,即奇数(对奇校验)或偶数(对偶检验),对数据中(除了校验位)的全部二进制1或0的数目进行校验。

      奇偶校验只能检测出错误而无法对其进行修正,同时虽然双位同时发生错误的概率相当低,但奇偶校验却无法检测出双位错误。

四、SC累加和校验

      SUM Check,简称SC。也有简称SC校验的,即Check SUM,校验和。 
      帧校验和为启动字符至校验和前的数据单字节算术累加和的低字节。 
      深圳传动之星变频器通信协议就采用了累加和校验。

五、S-XOR加总异或校验

SUM XOR Check,加总异或校验,也称之为异或校验和、累加异或校验和。在理解加总异或校验之前,我们先来了解一下什么是异或运算。

异或运算:参与运算的两个数各对应的二进位相异或,当两对应的二进位相异时,结果为1。

异或的运算方法是一个二进制运算: 
1^1=0 
0^0=0 
1^0=1 
0^1=1 
两者相等为0,不等为1. 

这样我们发现交换两个整数的值时可以不用第三个参数。 
如a=11,b=9.以下是二进制 
a=a^b=1011^1001=0010; 
b=b^a=1001^0010=1011; 
a=a^b=0010^1011=1001; 
这样一来a=9,b=13了。

0 xor 0 = 0 
1 xor 1 = 0 
0 xor 1 = 1 
1 xor 0 = 1

按位运算,不同的位置1,相同的位置0 
比如:69h xor 5Ah = 33h 

69h = 01101001b 
5Ah = 01011010b 
――――――――――― 
33h = 00110011b

说清楚点就是 二进制数按位运算时当对应的两位的值相同时(既都为1或0)那么该位xor的结果就是1,否则就为0,也就是相异则为1,否则为0。 
比如01101001异或01011010结果为00110011 
69h = 01101001b 
5Ah = 01011010b 
――――――――――― 
33h = 00110011b

采用Windows自带计算器进行异或运算: 
打开Windows自带的计算器,点击“查看”——“科学型”,选择“十六进制”,再输入“操作数1”、“Xor”、“操作数2”、“=”,就得出结果了@_@

加总异或有什么用呢?现在,很多设备的通信协议都采用了加总异或校验而不是累加和校验。例如丹麦丹佛斯Danfoss的变频器、其成员单位海利普的变频器都采用了加总异或校验。

言归正传,下面我们来看看怎么对下面的数据进行加总异或:

02 06 01 04 7C 40 00

计算 02 06 01 04 7C 40 00? 的加总异或值有以下几种方法:

1、采用Windows自带计算器进行异或运算:先计算02与06的异或值,然后把结果再和01异或。。。。。。一共进行6次异或计算,得到结果3D

2、采用现成的软件进行计算:例如大傻串口调试软件V4.5等软件,一次性就可以计算出来。

对于手工计算,有2种计算方法:1、 逐个字节异或;2、 把所有的字节先求和,再异或。下面的方法3和方法4就是这两种方法的体现。

3、手工计算:和方法1原理一样,只不过方法1是计算器,该方法是手工计算:

4、手工计算:和方法3原理一样,只不过方法3是一个一个计算,该方法是一起计算:

上速算法中,纵列相加,有奇数个1结果就等于1,有偶数个1结果就等于0。原理如下:异或运算是相同为0,不同为1;那么有多少个0都是0,所以可以不管零;那么有1个1,结果肯定为1;有2个1,结果就为0;有3个1,结果就为1。。。。。。

下面是《丹佛斯变频器VLT5000 RS485协议手册》(英文)中第15页对该计算方法的描述:


推荐阅读
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
author-avatar
lixinleslee
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有