标准的Modbus串行网络采用两种错误检测方法。 奇偶校验可逐字符使用,帧检测(LRC和CRC )适用于整个消息。 所有这些都由主设备在发送消息之前生成,从设备将在接收过程中检测每个字符和整个消息帧。
要让用户在主设备上设置预定义的超时间隔,所有从设备都必须有足够的时间间隔才能正常反应。 如果从设备检测到传输错误,则不会接收到消息,并且不会对主设备作出响应。 此类超时事件将触发主设备以处理错误。 不存在的从站的地址也将发生超时。
1、奇偶校验
如果指定了奇数或偶数检查,则“1”的位数将计算为每个字符的位数。 (在ASCII模式中为7位,在RTU中为8位)。 例如,RTU字符帧包含八个数据位:
1 1 0 0 0 1 0 1
“1”整体的数量是4个。 使用奇偶校验时,帧的奇偶校验位为0,整个“1”的个数保持为4。 在使用奇偶校验时,帧的奇偶校验位为1,使得整个“1”的个数为5个。
如果未指定奇偶校验位,则传输时没有奇偶校验位,也不进行检查。 填充要传输的字符帧,而不是附加的停止位。
2、LRC检查
使用ASCII模式时,消息包含基于LRC方法的错误检测域。 LRC字段检测到消息字段中除冒号和结束换行符外的内容。
LRC域是包含8位二进制文件的字节。 LRC值由发送设备计算并放置在消息帧中,接收设备在接收消息时计算LRC并将其与接收消息的LRC字段的值进行比较。 如果两个值不同,则会发生错误。
LRC方法连续累积消息中的8位字节,并丢弃进位。
LRC的简单函数如下。
1staticunsigedcharLRC(auchmsg,usDataLen )2 unsigned char *auchMsg; /*要计算的消息*
3 unsigned short usDataLen; /*LRC处理的字节数*
4 {5 unsigned char uchLRC=0; /*LRC字节初始化*
6发送6while(usdatalen----)/*消息(/
7 uchLRC =*auchMsg; /*累计(/
8return((unsignedchar ) ) (-) _uchLRC ); 9 }
LRC算法:
参与验证数据:从地址码到数据区的所有数据。
算法:把相邻的两个十六进制数加起来求和。
校验码:以其和的后8位补码作为校验码。
例如:
LRC算法示例
开始代码
地址代码
功能代码
数据区域
校验码
停止代码
:
01
03
21 02 00 02
LRC
CR/LF
合计: H01 H03 H21 H02 H00 02=H29
(H29的补数) HD7
LRC校验码是HD7
3、CRC检查
使用RTU模式时,消息包含基于CRC方法的错误检测域。 CRC域检测到了整个消息的内容。 CRC域是包含16位二进制值的双字节。 那个由传输设备计算并添加到消息中。 接收机重新计算接收到消息的CRC,并将该消息与接收的CRC域的值进行比较,如果两个值不同,则错误的。
CRC码的计算方法是先将所有16位寄存器预置为1。 逐步处理每8位数据信息。 在计算CRC码时,只使用8比特数据位、开始比特和停止比特,如果有奇偶校验位,也包括奇偶校验位,则不参与CRC码的计算。
在计算CRC码时,8位数据和寄存器的数据不同,或者把获得的结果移位低1字节,用0填充最高有效位。 进一步检查最低有效位,在最低有效位为1的情况下,寄存器的内容与预置数不同,或者在最低有效位为0的情况下,不进行异或运算。
这个过程一直重复8次。 在第8次移位后,接下来的8位与当前的寄存器的内容不同,或者与上述相同地重复8次该过程。 所有数据处理后,最终寄存器的内容变为CRC代码值。 收发CRC代码中的数据时,低字节先。
要计算CRC代码,请执行以下操作:
预置16位寄存器是十六进制的FFFF (即全部为1 )。 该寄存器称为CRC寄存器;
使前8位数据与16位CRC寄存器低位不同,或者将结果放在CRC寄存器中;
将寄存器的内容向右移动一位(朝向下位),用0填充最高位,检查最低位
如果最低有效位为0,则重复步骤3 (重新移位); 在最低有效位为1情况下,CRC寄存器和多项式a001(1010000000000001 )的异或;
重复步骤3和4,直到向右移动8次,从而处理了整个8位数据;
重复步骤2到步骤5,进行下一个8位数据的处理;
最后得到的CRC寄存器是CRC码。
参考: http://www.360doc.com/content/14/0120/10/7991404 _ 346584755.shtml