IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Modbus ASCII LRC生成 -> 正文阅读

[网络协议]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要求起始符必须是两个字节。当然,为了解决这一问题,PLC厂商也会提供相应的硬件模块,不过是钱的问题。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:51:11  更:2021-07-13 17:51:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 12:57:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计