Modbus ASCII LRC生成
Modbus ASCII的报文生成顺序为:
1、生成PDU
2、生成LRC校验码,将LRC附加到PDU后面
3、将2中的数组转换成HEX格式的文本
4、在HEX格式文本的0位置插入冒号,在HEX格式文本的后面附加Windows换行符
生成LRC的公式为:LRC = - sum(PDU)
以下为LRC校验码生成算法的通用性示范:
/**将HEX格式的数据流包装成字符串对象*/public static final int getLRC8FromAscIIBytes(byte[] hex, int first, int last) {String hexString = new String(hex, Math.min(first, last), Math.max(first, last) + 1);return getLRC8FromAscIIBytes(hexString, 0, hexString.length() - 1);}/**将字符串对象解码为Modbus数据*/public static int getLRC8FromAscIIBytes(String hex, int first, int last) {if (hex == null || hex.isEmpty()) {return 0;}String subHex = hex.substring(Math.min(first, last), Math.max(first, last) + 1);byte[] bytes = convertHexStringToBytes(subHex);if (first < last) {return getLRC8FromRealBytes(bytes, 0, bytes.length - 1);} else {return getLRC8FromRealBytes(bytes, bytes.length - 1, 0);}}/**将Modbus数据求和,变为负数,返回低字节,即Modbus ASCII LRC8校验码的值*/public static final int getLRC8FromRealBytes(byte[] bytes, int first, int last) {if (bytes == null) {return 0;}return (-getADD8(bytes, first, last)) & 0xff;}/**求和函数*/public static final int getADD8(byte[] bytes, int first, int last) {if (bytes == null) {return 0;}byte result = 0;int step = (first < last) ? 1 : -1;for (int i = first; i != last + step; i += step) {result += bytes[i];}return result & 0xff;}
需要注意的是,这里的函数专门用于Modbus ASCII校验,不同的通信规约中对LRC的定义可能不一样。LRC8是对字节统计求和校验的包装,包装的方法不唯一。对Modbus ASCII而言,包装的目的在于使有效报文字节(排除掉首字节和Windows换行符共3个字节的常量部分)的统计和为0。这一点也体现在Modbus RTU的CRC16校验上。
一些相关问题
为什么Modbus TCP不需要这种归零校验码?
归零校验码的作用在于快速确定报文是否结束,而无需等待最后一步超时。Modbus TCP带有报文长度信息,所以不需要归零。另外,TCP层自带通信数据校验,其可靠性强于应用层及会话层的校验,因此Modbus TCP的应用层规约中没有校验的规定。但由于尾部空闲数据区未进行封闭性的定义,开发者也可以自己增加几个字节的校验码,甚至可将MD5放到后面,这样即有校验码又能兼容不做校验的程序。
为什么有了归零校验码,Modbus ASCII仍然需要需要Windows换行符来结尾?
这样可以兼容一些缓冲字符流。比如Java中的BufferedReader就需要这个换行符才能知道这段报文已经结束了。至于为什么是Windows换行符,那是因为Windows换行符可以兼容Linux和iOS,反之则不能通用。另外,几乎所有上位机工业软件都运行于Windows系统,采用Windows换行符是大势所趋。使用Windows换行符来作为结束符无可厚非,但Mosbus ASCII报文的起始符是一个败笔。单一字节的起始符可能无法兼容一些PLC。比如欧姆龙PLC要求起始符必须是两个字节。一种简单粗暴的解决办法是在起始符前面添加一个不同于起始符的字节(比如添加一个空格或空字符)凑成两个字节。
Modbus ASCII LRC生成相关推荐
- Modbus协议栈应用实例之六:Modbus ASCII从站应用
自从开源了我们自己开发的Modbus协议栈之后,有很多朋友建议我针对性的做几个示例.所以我们就基于平时我们的应用整理了几个简单但可以说明基本的应用方法的示例,这一篇中我们来使用协议栈实现Modbus ...
- Modbus协议栈应用实例之五:Modbus ASCII主站应用
自从开源了我们自己开发的Modbus协议栈之后,有很多朋友建议我针对性的做几个示例.所以我们就基于平时我们的应用整理了几个简单但可以说明基本的应用方法的示例,这一篇中我们来使用协议栈实现Modbus ...
- modbus协议和串口服务器,Modbus RTU通信模式与Modbus ASCII通信模式的异同点
Modbus基于串行通信存在两种模式:Modbus RTU与Modbus ASCII模式,不管是RTU模式还是ASCII模式,Modbus信息都以帧的方式传输,每个信息帧有确定的起始点和结束点,使接收 ...
- Modbus协议栈开发笔记之八:Modbus ASCII Master开发
这一节我们来封装Modbus ASCII Master应用,Modbus ASCII主站的开发与RTU主站的开发是一致的.同样的我们也不是做具体的应用,而是实现ASCII主站的基本功能.我们将ASCI ...
- Modbus协议栈开发笔记之七:Modbus ASCII Slave开发
与Modbus RTU在串行链路上分为Slave和Master一样,Modbus ASCII也分为Slave和Master,这一节我们就来开发Slave.对于Modbus ASCII从站来说,需要实现 ...
- 详细解读Modbus RTU、Modbus ASCII、Modbus TCP的区别
Modbus 是Modicon公司于1979年开发的串行通信协议.它最初设计用于公司的可编程逻辑控制器(PLC). Modbus是一种开放式协议,支持使用RS232/RS485/RS422协议的串行设 ...
- 实现Modbus ASCII多主站应用
前面我们已经分析了Modbus RTU的更新设计和具体实现(如果不清楚可查看前一篇文章).其实Modbus ASCII与Modbus RTU都是基于串行链路实现的,所以有很多的共同点,基于此,这篇文章 ...
- java modbus lrc,Modbus ASCII RTU LRC CRC 校验
RTU即Remote Terminal Unit的缩写,中文译为远程终端装置. CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征 ...
- MODBUS ASCII协议和RTU协议的比较 -----和利时PLC采用Modbus RTU
通过比较可以看到,ASCII协议和RTU协议相比拥有开始和结束标记,因此在进行程序处理时能更加方便,而且由于传输的都是可见的ASCII字符,所以进行调试时就更加的直观,另外它的LRC校验也比较容易.但 ...
最新文章
- linux防火墙 33001端口,Linux操作系统下IPTables配置方法详解
- python魔法函数和装饰器_python魔法方法、构造函数、序列与映射、迭代器、生成器...
- 重理工c语言实验指导书,太原理工大学级c语言实验指导书参考答案教程方案.docx...
- 【Python之旅】第二篇(七):集合
- 【Day 1】机器阅读理解——机器阅读理解简介
- centos7更改默认的python版本,安装python3.6.4
- LeetCode 141. Linked List Cycle 判断链表是否有环 C++/Java
- 完全平方数的几种判定方法与算法用时
- C语言 求100--200之间的素数
- shapely中几何对象
- 使用ZED相机录制事件双目数据集
- 处理一次 MYSQL 启动异常 Error writing file '/tmp/MYYEBa32' (Errcode: 28 - No space left on device)
- 华为服务器维护客服,服务器客服
- 众人坐下以后,苏睿好不容易找来了几个茶碗
- 如何通过JMeter测试金仓数据库KingbaseES并搭建环境
- 处理setInterval造成的浏览器内存溢出
- mysql设某个值为empty_oracle 修改某字段小数位精度 需要字段未empty的解决办法
- 如何创建一个简单的买卖止盈止损分时买卖框架 1
- chacha20算法,适用于单片机
- 子曰:不患人之不己之,患不知人也。