一.什么是modbus

Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于工业现场的总线协议。
ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。
  ModBus网络只有一个主机,所有通信都由他发出。网络可支持247个之多的远程从属控制器,但实际所支持的从机数要由所用通信设备决定。采用这个系统,各PC可以和中心主机交换信息而不影响各PC执行本身的控制任务。

二.Java实现modbus协议通讯

Java编程中,使用modbus4j实现Java中的modbus协议通讯

modbus4j实现了Java与modbus协议的以下几种通讯方式:
modbus TCP/IP通讯
modubs UDP/IP通讯
modbus RTU/IP通讯

核心依赖:
modbus4j.jar
commons-lang3-3.0.jar
//下载地址代码里有
Java读取工具类

package com.leftso.project.demo.modbus4j;import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;/*** modbus通讯工具类,采用modbus4j实现* * @author lxq* @dependencies modbus4j-3.0.3.jar* @website https://github.com/infiniteautomation/modbus4j*/
public class Modbus4jUtils {/*** 工厂。*/static ModbusFactory modbusFactory;static {if (modbusFactory == null) {modbusFactory = new ModbusFactory();}}/*** 获取master* * @return* @throws ModbusInitException*/public static ModbusMaster getMaster() throws ModbusInitException {IpParameters params = new IpParameters();params.setHost("localhost");params.setPort(502);//// modbusFactory.createRtuMaster(wapper); //RTU 协议// modbusFactory.createUdpMaster(params);//UDP 协议// modbusFactory.createAsciiMaster(wrapper);//ASCII 协议ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议master.init();return master;}/*** 读取[01 Coil Status 0x]类型 开关数据* * @param slaveId*            slaveId* @param offset*            位置* @return 读取值* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常* @throws ModbusInitException*             异常*/public static Boolean readCoilStatus(int slaveId, int offset)throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 01 Coil StatusBaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);Boolean value = getMaster().getValue(loc);return value;}/*** 读取[02 Input Status 1x]类型 开关数据* * @param slaveId* @param offset* @return* @throws ModbusTransportException* @throws ErrorResponseException* @throws ModbusInitException*/public static Boolean readInputStatus(int slaveId, int offset)throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 02 Input StatusBaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);Boolean value = getMaster().getValue(loc);return value;}/*** 读取[03 Holding Register类型 2x]模拟量数据* * @param slaveId*            slave Id* @param offset*            位置* @param dataType*            数据类型,来自com.serotonin.modbus4j.code.DataType* @return* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常* @throws ModbusInitException*             异常*/public static Number readHoldingRegister(int slaveId, int offset, int dataType)throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 03 Holding Register类型数据读取BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);Number value = getMaster().getValue(loc);return value;}/*** 读取[04 Input Registers 3x]类型 模拟量数据* * @param slaveId*            slaveId* @param offset*            位置* @param dataType*            数据类型,来自com.serotonin.modbus4j.code.DataType* @return 返回结果* @throws ModbusTransportException*             异常* @throws ErrorResponseException*             异常* @throws ModbusInitException*             异常*/public static Number readInputRegisters(int slaveId, int offset, int dataType)throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 04 Input Registers类型数据读取BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);Number value = getMaster().getValue(loc);return value;}/*** 批量读取使用方法* * @throws ModbusTransportException* @throws ErrorResponseException* @throws ModbusInitException*/public static void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException {BatchRead<Integer> batch = new BatchRead<Integer>();batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT));batch.addLocator(1, BaseLocator.inputStatus(1, 0));ModbusMaster master = getMaster();batch.setContiguousRequests(false);BatchResults<Integer> results = master.send(batch);System.out.println(results.getValue(0));System.out.println(results.getValue(1));}/*** 测试* * @param args*/public static void main(String[] args) {try {// 01测试Boolean v011 = readCoilStatus(1, 0);Boolean v012 = readCoilStatus(1, 1);Boolean v013 = readCoilStatus(1, 6);System.out.println("v011:" + v011);System.out.println("v012:" + v012);System.out.println("v013:" + v013);// 02测试Boolean v021 = readInputStatus(1, 0);Boolean v022 = readInputStatus(1, 1);Boolean v023 = readInputStatus(1, 2);System.out.println("v021:" + v021);System.out.println("v022:" + v022);System.out.println("v023:" + v023);// 03测试Number v031 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,floatNumber v032 = readHoldingRegister(1, 3, DataType.FOUR_BYTE_FLOAT);// 同上System.out.println("v031:" + v031);System.out.println("v032:" + v032);// 04测试Number v041 = readInputRegisters(1, 1, DataType.FOUR_BYTE_FLOAT);//Number v042 = readInputRegisters(1, 3, DataType.FOUR_BYTE_FLOAT);//System.out.println("v041:" + v041);System.out.println("v042:" + v042);// 批量读取batchRead();} catch (Exception e) {e.printStackTrace();}}
}

三、测试

使用ModbusSlave模拟modbus协议
slave中模拟数据如下

运行工具类的main方法:

11:14:54.547 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 00 00 01
11:14:54.550 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.598 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01
11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 01 00 01
11:14:54.600 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.650 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 00
11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 01 00 06 00 01
11:14:54.652 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.703 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 01 01 01
v011:true
v012:false
v013:true
11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01
11:14:54.704 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.755 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01
11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 01 00 01
11:14:54.757 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.807 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 00
11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 02 00 01
11:14:54.810 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.860 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01
v021:true
v022:false
v023:true
11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 01 00 02
11:14:54.866 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.915 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 40 20 00 00
11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 03 00 03 00 02
11:14:54.917 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:54.967 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 03 04 41 28 00 00
v031:2.5
v032:10.5
11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 01 00 02
11:14:54.971 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:55.020 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 3F C0 00 00
11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 04 00 03 00 02
11:14:55.021 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:55.072 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 07 01 04 04 40 40 00 00
v041:1.5
v042:3.0
11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 00 00 00 00 06 01 02 00 00 00 01
11:14:55.074 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:55.123 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 00 00 00 00 04 01 02 01 01
11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Encap Request: 00 01 00 00 00 06 01 03 00 01 00 02
11:14:55.125 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Sending on port: 502
11:14:55.179 [main] DEBUG com.serotonin.modbus4j.ip.tcp.TcpMaster - Response: 00 01 00 00 00 07 01 03 04 40 20 00 00
2.5
true

观察输出结果与 slave上的模拟数据一致

四、Java通过modbus4j对数据的写入

Modbus4jWriteUtils.java

package com.leftso.project.demo.modbus4j;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.ModbusResponse;
import com.serotonin.modbus4j.msg.WriteCoilRequest;
import com.serotonin.modbus4j.msg.WriteCoilResponse;
import com.serotonin.modbus4j.msg.WriteCoilsRequest;
import com.serotonin.modbus4j.msg.WriteCoilsResponse;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;/*** modbus4j写入数据* * @author xq**/
public class Modbus4jWriteUtils {static Log log = LogFactory.getLog(Modbus4jWriteUtils.class);/*** 工厂。*/static ModbusFactory modbusFactory;static {if (modbusFactory == null) {modbusFactory = new ModbusFactory();}}/*** 获取tcpMaster* * @return* @throws ModbusInitException*/public static ModbusMaster getMaster() throws ModbusInitException {IpParameters params = new IpParameters();params.setHost("localhost");params.setPort(502);ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false);tcpMaster.init();return tcpMaster;}/*** 写 [01 Coil Status(0x)]写一个 function ID = 5* * @param slaveId*            slave的ID* @param writeOffset*            位置* @param writeValue*            值* @return 是否写入成功* @throws ModbusTransportException* @throws ModbusInitException*/public static boolean writeCoil(int slaveId, int writeOffset, boolean writeValue)throws ModbusTransportException, ModbusInitException {// 获取masterModbusMaster tcpMaster = getMaster();// 创建请求WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);// 发送请求并获取响应对象WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);if (response.isException()) {return false;} else {return true;}}/*** 写[01 Coil Status(0x)] 写多个 function ID = 15* * @param slaveId*            slaveId* @param startOffset*            开始位置* @param bdata*            写入的数据* @return 是否写入成功* @throws ModbusTransportException* @throws ModbusInitException*/public static boolean writeCoils(int slaveId, int startOffset, boolean[] bdata)throws ModbusTransportException, ModbusInitException {// 获取masterModbusMaster tcpMaster = getMaster();// 创建请求WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);// 发送请求并获取响应对象WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);if (response.isException()) {return false;} else {return true;}}/**** 写[03 Holding Register(4x)] 写一个 function ID = 6* * @param slaveId* @param writeOffset* @param writeValue* @return* @throws ModbusTransportException* @throws ModbusInitException*/public static boolean writeRegister(int slaveId, int writeOffset, short writeValue)throws ModbusTransportException, ModbusInitException {// 获取masterModbusMaster tcpMaster = getMaster();// 创建请求对象WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);if (response.isException()) {log.error(response.getExceptionMessage());return false;} else {return true;}}/*** * 写入[03 Holding Register(4x)]写多个 function ID=16* * @param slaveId*            modbus的slaveID* @param startOffset*            起始位置偏移量值* @param sdata*            写入的数据* @return 返回是否写入成功* @throws ModbusTransportException* @throws ModbusInitException*/public static boolean writeRegisters(int slaveId, int startOffset, short[] sdata)throws ModbusTransportException, ModbusInitException {// 获取masterModbusMaster tcpMaster = getMaster();// 创建请求对象WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);// 发送请求并获取响应对象ModbusResponse response = tcpMaster.send(request);if (response.isException()) {log.error(response.getExceptionMessage());return false;} else {return true;}}/*** 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long)* * @param slaveId* @param offset* @param value*            写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long* @param registerCount*            ,com.serotonin.modbus4j.code.DataType* @throws ModbusTransportException* @throws ErrorResponseException* @throws ModbusInitException*/public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType)throws ModbusTransportException, ErrorResponseException, ModbusInitException {// 获取masterModbusMaster tcpMaster = getMaster();// 类型BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);tcpMaster.setValue(locator, value);}public static void main(String[] args) {try {//@formatter:off// 测试01
//          boolean t01 = writeCoil(1, 0, true);
//          System.out.println("T01:" + t01);// 测试02
//          boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true });
//          System.out.println("T02:" + t02);// 测试03
//          short v = -3;
//          boolean t03 = writeRegister(1, 0, v);
//          System.out.println("T03:" + t03);// 测试04
//          boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 });
//          System.out.println("t04:" + t04);//写模拟量writeHoldingRegister(1,0, 10.1f, DataType.FOUR_BYTE_FLOAT);//@formatter:on} catch (Exception e) {e.printStackTrace();}}}

modbus协议中常见功能代码说明:

modbus tcp通讯modbus4j使用说明相关推荐

  1. 基于STM32和W5500的Modbus TCP通讯

     在最近的一个项目中需要实现Modbus TCP通讯,而选用的硬件平台则是STM32F103和W5500,软件平台则选用IAR EWAR6.4来实现. 1.移植前的准备工作 为了实现Modbus ...

  2. winpcapp配置c++网口通讯_(经验)西门子PLC的Modbus TCP通讯的一些经验

    Modbus是一种协议公开的工业通讯,被广泛使用.通过串口的是Modbus-RTU协议,通过以太网的是Modbus TCP通讯.现在的PLC都开始支持以太网通讯,因此,Modbus TCP也越来越重要 ...

  3. 三菱PLC FX5U与FX5U 直间modbus tcp 通讯

    三菱PLC FX5U与FX5U 直间modbus tcp 通讯 (与此程序经过设备多次使用,硬件一样可以直接用 id=644700625705&

  4. Labview 和信捷 XDH PLC Modbus tcp通讯

    本文描述Labview 和信捷 XDH PLC Modbus tcp通讯,实际测试. 以XDH-60T4-E为实验. 1.地址 1.1默认IP地址:192.168.6.6,端口号:502 1.2点位地 ...

  5. 客户机和服务器在s7通信中各有什么作用,哪些通信口可以进行 Modbus TCP 通讯,作为 Modbus 服务器的 SIMATIC S7 CPU 可以...

    以下通信端口可用于 Modbus/TCP 协议:在默认情况下,端口号 502 作为 Modbus 服务器的本地端口. 可以在 Modbus 客户机中设置需要的本地端口,通常使用从 2000 开始的端口 ...

  6. c#modbus tcp通讯助手开源_RS485和Modbus知识点汇总

    RS485 RS485 特点: 1.逻辑"1"以两线间的电压差为+(2-6)V表示:逻辑"0"以两线间的电压差为-(2-6)V表示.接口信号电平比RS232降低 ...

  7. 两台codesys设备之间通过modbus TCP通讯案例

    目录 关于modbus TCP server端的设置如下 关于modbus TCP clietn端的设置如下 本案例中N1小白盒codesys作为modbus TCP server端,PC的codes ...

  8. 西门子PLC S7-200SMART Modbus TCP通讯的步骤和要点

    Modbus TCP是一个非常传统,应用广泛的通讯协议,很多智能设备都支持该协议.西门子S7-200SMART及1200.1500系列都免费支持(300和400还是要高昂收费),并且做成了标准库,使用 ...

  9. Modbus TCP通讯协议

    一.简介 Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准.1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP. Modbus协议是一项应 ...

最新文章

  1. linux安装的时候网卡配置失败,Linux下安装网卡执行make install失败
  2. JDBC连接时所犯错误1.字符集设置不合适2.连接MySQL8.0社区版时时区不一致3..包名不能以Java.命名4.驱动被弃用
  3. leetcode-44. Wildcard Matching
  4. GitHub 新出的 Actions 是什么? 用他做自动测试?
  5. 重温 const 指针
  6. Unity 5.x---00使用重力
  7. (转)Three.JS学习 9:WEBVR 入门demo
  8. Java的Number和Math类
  9. 【干货】python爬取《战狼2》电影短评论,生成图云
  10. IDEA中修改html页面后在浏览器不生效的解决方法
  11. linux硬件测试拷机软件,“拷机”中。
  12. Java分解整型质因数
  13. Codeforces Round #717 (Div. 2)(ABCD)
  14. 不可错过的五款开源图形处理软件
  15. 大学生如何奋斗5年从月薪3500到700万
  16. 分布式系统:概念,优缺点,架构,路线,设计,原理,演变,主流框架,工具,可靠性,问题,技术联系,总结,定制
  17. sqlserver 的查询最近7天的数据 group by 与with的结合 以及系统表的妙用
  18. 【Java项目实战】在线音乐播放器(从需求到产品完整解析)
  19. 80c51的c语言程序设计,第10章80C51的C语言程序设计
  20. IP地址,子网掩码,默认网关

热门文章

  1. 错误解决---void value not ignored as it ought to be
  2. 隐藏通知内容什么意思_隐藏通知内容
  3. 计算机初级职称答辩题,中小学职称评选答辩问题集锦
  4. 处理R安装后出现You're using a non-UTF8 locale, therefore only ASCII characters will work.的情况
  5. 安卓仿苹果音量调节_android自定义view仿照MIUI中音量控制效果
  6. 微信编辑器都有什么功能?
  7. 前端Bani Yas
  8. BA-中央空调冰蓄冷(视频)
  9. WindRiver.Tornado.v2.2.for.Mips-ISO 2CD
  10. 位运算以及位运算的应用