2 Star 7 Fork 5

大话家 / modbusTcp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
README.md 5.89 KB
一键复制 编辑 原始数据 按行查看 历史
大话家 提交于 2022-02-14 14:14 . readme

项目说明

本项目是在云逸的博客文章(https://www.cnblogs.com/ioufev/p/10831289.html)为基础,在其给出的demo的基础上做学习和修改。
本项目中介绍了JLibModbus、Modbus4J、ModbusMasterTcp三种框架的用法,即对应项目中的三个包,值得注意的是,本项目将尝试使用java socket
直接对接modbus,以求加深对modbus的理解。

其他

Modbus是一种串行通信协议。Modbus 一个工业上常用的通讯协议、一种通讯约定。 Modbus协议包括RTU、ASCII、TCP。其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现。
这些Modbus的框架似乎并不支持修改Discrete(0x03)状态数据和InputRegister(0x04)寄存器数据。

分支说明

master
主要是三种框架(jLibModbus、modbus4J、modbusMasterTCP)的读写示例,socket读写示例,IEEE745标准等。

spring
SpringBoot整合modbusMasterTCP框架协议。

Modbus Slave仿真软件的几点说明

Connection -> Auto Connect -> (Enable/Disable)

这里的自动连接是指,是否在软件启动后自动创建Slave链接。

Ignore Unit ID

勾上这个选项,那么当主机(master)连接从机(slave)时,将会忽略slaveId。即只区分功能代码,不区分从机ID。
即使主机待连接的从机ID不存在,也不会报错,只会返回相同功能代码的第一个从机数据。即使后面该ID的从机上线也无效。
如果不勾选,则会对功能代码和从机ID都进行匹配。

框架问题说明

modbus-master-tcp

较为复杂,扩展性强,(异步)底层使用了Netty框架,需要有一定的Java NIO知识。
更新频率和使用情况

jlibmodbus

API文档:https://libmodbus.org/docs/v3.0.6/ 简单易用,扩展性差,性能一般。读取的数据类型只能为整数,需要自己转换。 更新频率和使用情况

modbus4j

无法直接通过maven官方仓库下载,需要先下载至本地。 更新频率和使用情况

报文格式

modbusTCP报文格式

modbus TCP 发送报文格式

示例:new byte[]{a, b, c, d, e, f, g, h, i, j, k, l} 共12个byte

MBAP报文头一般为7个字节(a, b, c, d, e, f, g),其中:
ab为传输标识符,可以设置为0,也可以设置为每次传输只增1。
cd为协议标识符,其中0000代表ModbusTCP协议,0001代表UNI-TE协议。
ef为后续报文长度,为报文剩下的所有字节数。
g为单元标识符,即设备ID,在MODBUS或MODBUS+串行链路子网中对设备进行寻址时,这个域是用于路由的目的地址。
h为功能码,常见的功能码有:

01:读取线圈状态(单个或多个)
02:读取离散输入状态(单个或多个)
03:读取保持寄存器数据(单个或多个)
04:读取输入寄存器数据(单个或多个)
05:写入单个线圈状态
06:写入单个保持寄存器数据
15:写入多个线圈状态
16:写入多个保持寄存器数据

ij为起始地址,kl为读取数量

modbus TCP 响应报文格式

示例:new byte[]{a, b, c, d, e, f, g, h, i, j1, j2, j3 ...} byte 数量不固定

其中,前7个字节(a, b, c, d, e, f, g)为MBAP报文头,h为功能码,i为数据报文长度,j1、j2、j3 ... 为返回数据内容。

大端与小端问题

根据IEEE754的标准,浮点数的存储至少需要32为bit,而一个地址只有16个bit,因此则要进行拆分,就涉及到存储顺序的问题,可以分为大端模式或小端模式。
小端:将低序字节存储在起始地址。大端:将高序字节存储在起始地址。
在本项目中,并没有考虑到大端和小端的问题,统一采用小端标准,因为小端标准更为复杂,改成大端标准也更为容易。
Modbus Slave软件中的修改步骤如下:
Format --> 32 Bit Float / 64 Bit Double --> Big-endian / Little-endian

附注

附注1

例如,从机数据为:

index value
0 1
1 1
2 1
3 0
4 0
5 0
6 0
7 0
8 1
9 1

则在响应报文数组中,数值数组第一个值为7(00000111),第二个值为3(11)

附注2

这些方法的参数quantity(需要读取的数量),这里的数量指的是地址数量,而不是数据的数量。因为不同类型的寄存器和不同的数据类型,在数据存储上均有差别,无法一概而论。

  • 线圈(0x01)和离散输入(0x02)只能存储状态布尔值,其一个地址就只有一个binary位,就存储一个数据量。

  • 保持寄存器(0x03)和输入寄存器(0x04)一个地址有16个bit位,前8位和后8位组成两个byte数据。
    二进制数、有/无符号十进制数、十六进制数一个数据量,即对应一个地址数量;
    按照IEEE754标准,一个单精度浮点数需要32位bit,即对应两个地址数量,最多能精确7位有效数字;
    按照IEEE754标准,一个双精度浮点数需要64位bit,即对应四个地址数量,最多能精确15位有效数字;

  • 同时也需要注意,这些bit并非按顺序存储,而是按以下步骤:
    1、判断长度是否是8的倍数,不足则高位补0,补成0的倍数
    2、8位一组分组
    3、按小端模式,高位存储在高地址

  • 例如:浮点数123.4556,对应的二进制为:01000010 11110110 11101001 01111001 (本来就是32位)

地址 数值
0 0100 0010 1111 0110
1 1110 1001 0111 1001
1
https://gitee.com/dahuajia/modbusTcp.git
git@gitee.com:dahuajia/modbusTcp.git
dahuajia
modbusTcp
modbusTcp
master

搜索帮助