当前位置:
首页 >
行业知识 >
Modbus通讯协议——Java通过Jlibmodbus实现Modbus Master(主机)TCP/RTU的Read;Slave(从机)TCP/RTU的Write
行业知识
Modbus通讯协议——Java通过Jlibmodbus实现Modbus Master(主机)TCP/RTU的Read;Slave(从机)TCP/RTU的Write
2026-10-26 14:11:17
来源:互联网转载
一、首先了解一下Java实现Modbus的三种jar包
()只做参考,有能力的话还是建议根据需求自行编写协议工具类
1. modbus4: 支持Modbus-RTU、 Modbus-ASCl.Modbus-TCP三种协议,支持Modbus-RTU over Senal, Modbus.RTU over TCPUDP、 Modbus-ASCl over sera
()和 Modbus-TCP over TCP/UDP。但是该工具是同步的不支持异步,实时性要求不强可以使用。
2. ililbmodbus:支持Modbus-RTU和Modbus-TCP两种协议,支持Modbus-RTU over Serial、Modbus-RTU over TCP
Modbus-TCP over TCP,Modbus-TCP内部通
过socket实现支持异步。Modbus-RTU Serial通过RXTX实现。
modbus-master-tcp:支持Modbus-TCP一种协议,支持Modbus-TCP over TCP,内部通过netty实现支持异步。
可以执行扩展使其支持Modbus-RTU over TCP和Moc
bus-RTU over Serial
二、主要针对Jlibmodbus实现Modbus的主机与从机’
1、导入依赖
另附Maven仓库地址:https://mvnrepository.com/
com.intelligt.modbus jlibmodbus 1.2.9.10
2、Master主机模式:
1)、Modbus-TCP
import com.intelligt.modbus.jlibmodbus.Modbus;import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;import java.math.BigDecimal;import java.math.BigInteger;import java.net.InetAddress;public class JlibmodbusMasterTcpReader { public static void main(String[] args) throws Exception { TcpParameters tcpParameters = new TcpParameters(); tcpParameters.setHost(InetAddress.getByName("127.0.0.1")); tcpParameters.setPort(502); tcpParameters.setKeepAlive(true); int[] num = {1}; for (int n : num){ int[] ints = new JlibmodbusMasterTcpReader().modbusReads(n,tcpParameters); System.out.println(ints[0]); int second = ints[0]; int first = ints[1]; System.out.println(ints[1]);// for (int m : ints){// System.out.print(m);// } //在进行字符串转化时,转化的16进制会存在缺少一位的情况,进行左侧补零操作 String hexStr = addZeroForStr(Integer.toHexString(first),4,1)+""+addZeroForStr(Integer.toHexString(second),4,1); System.out.println(new BigDecimal(sfloat(hexStr))); System.out.println(); } } public int[] modbusReads(int serverAddress, TcpParameters tcpParameters) throws Exception { ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters); master.setResponseTimeout(3000); master.connect(); Modbus.setAutoIncrementTransactionId(true); int[] result = master.readInputRegisters(serverAddress,0, 10); master.disconnect(); return result; } //将字符串类型的16进制数据,转化为float字符串 private static String sfloat(String str){ Float value = Float.intBitsToFloat(new BigInteger(str, 16).intValue()); return String.valueOf(value); } /** * 给字符串的左补0或右补0 * @param str 要处理的字符串 * @param length 补0后字符串总长度 * @return 返回补零字符串 */ public static String addZeroForStr(String str, int length, int type) { int strLen = str.length(); if (strLen 2)、Modbus-RTU
import com.intelligt.modbus.jlibmodbus.Modbus;import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;import com.intelligt.modbus.jlibmodbus.serial.*;import java.io.*;public class JlibmodbusMasterRtuReader { public static void main(String[] args) throws Exception { SerialParameters params = new SerialParameters(); params.setDevice("COM2"); // 串口名称 params.setBaudRate(SerialPort.BaudRate.getBaudRate(9600)); // 波特率 params.setDataBits(8); // 数据位 params.setStopBits(1); // 停止位 params.setParity(SerialPort.Parity.getParity(0)); // 无校验 ModbusMaster master = ModbusMasterFactory.createModbusMasterRTU(params); Modbus.setAutoIncrementTransactionId(true); master.connect(); int[] registers = master.readHoldingRegisters(1, 0, 10); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("C:\Users\user\Desktop\data.txt")); for (int reg : registers){ System.out.println(reg); bufferedWriter.write(reg + " "); } bufferedWriter.newLine(); bufferedWriter.close(); master.disconnect(); }} 3、Slave-从机模式
1)、Modbus-TCP
import com.intelligt.modbus.jlibmodbus.Modbus;import com.intelligt.modbus.jlibmodbus.data.DataHolder;import com.intelligt.modbus.jlibmodbus.data.ModbusCoils;import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters;import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;import com.intelligt.modbus.jlibmodbus.slave.ModbusSlave;import com.intelligt.modbus.jlibmodbus.slave.ModbusSlaveFactory;import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;import java.net.InetAddress;import java.util.ArrayList;import java.util.List;public class JlibmodbusSlaveTcpWriter { public static void main(String[] args) { try { // 设置从机TCP参数 TcpParameters tcpParameters = new TcpParameters(); // 设置TCP的ip地址 InetAddress address = InetAddress.getByName("127.0.0.1"); // getLocalHost()返回的是本机地址 // tcpParameters.setHost(InetAddress.getLocalHost()); // 为从机TCP设置上述ip地址参数 tcpParameters.setHost(address); // 设置从机TCP的是否长连接,通俗点讲就是一直保持连接,一次连接完下次就不要在连接了 tcpParameters.setKeepAlive(true); // 设置从机TCP的端口 tcpParameters.setPort(Modbus.TCP_PORT); // 创建一个从机 ModbusSlave slave = ModbusSlaveFactory.createModbusSlaveTCP(tcpParameters); // 设置控制台输出主机和从机命令交互日志 Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG); // 创建从机的寄存器 MyOwnDataHolder dh = new MyOwnDataHolder(); // 为从机寄存器添加监听事件,这里的监听事件主要是主机如果发送写命令修改从机则控制台输出 dh.addEventListener(new ModbusEventListener() { @Override public void onWriteToSingleCoil(int address, boolean value) { System.out .print("onWriteToSingleCoil: address " + address + ", value " + value); } @Override public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) { System.out.print("onWriteToMultipleCoils: address " + address + ", quantity " + quantity); } @Override public void onWriteToSingleHoldingRegister(int address, int value) { System.out.print("onWriteToSingleHoldingRegister: address " + address + ", value " + value); } @Override public void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values) { System.out.print("onWriteToMultipleHoldingRegisters: address " + address + ", quantity " + quantity); } }); // 为从机设置寄存器 slave.setDataHolder(dh); // 设置从机的读超时时间,建议主机读的超时时间小于该值 slave.setReadTimeout(1500); // 设置从机寄存器的03和04功能码对应的数值寄存器 ModbusHoldingRegisters hr = new ModbusHoldingRegisters(10); // 修改数值寄存器对应位置的值,第一个参数代表寄存器地址,第二个代表修改的数值 hr.set(0, 12345); hr.set(1, 54321); // 设置从机寄存器的01和02功能码对应的位寄存器,即只有false和true值(或0和1) ModbusCoils mc = new ModbusCoils(16); // 设置对应位寄存器地址的位值 mc.set(0, true); // 为从机设置04功能码对应的数值寄存器 slave.getDataHolder().setInputRegisters(hr); // 为从机设置03功能码对应的数值寄存器 slave.getDataHolder().setHoldingRegisters(hr); // 为从机设置01功能码对应的数值寄存器// slave.getDataHolder().setCoils(mc); // 为从机设置从机服务地址slaveid slave.setServerAddress(1); // 开启从机监听事件,必须要这一句 slave.listen(); //这部分代码主要是设置Java虚拟机关闭的时候需要做的事情,即本程序关闭的时候需要做的事情,直接使用即可 if (slave.isListening()) { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { synchronized (slave) { slave.notifyAll(); } } }); synchronized (slave) { slave.wait(); } /* * using master-branch it should be #slave.close(); */ slave.shutdown(); } } catch (RuntimeException e) { throw e; } catch (Exception e) { e.printStackTrace(); } } // 监听接口 public interface ModbusEventListener { void onWriteToSingleCoil(int address, boolean value); void onWriteToMultipleCoils(int address, int quantity, boolean[] values); void onWriteToSingleHoldingRegister(int address, int value); void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values); } // 寄存器类定义 public static class MyOwnDataHolder extends DataHolder { final List modbusEventListenerList = new ArrayList(); public MyOwnDataHolder() { // you can place the initialization code here /* * something like that: setHoldingRegisters(new * SimpleHoldingRegisters(10)); setCoils(new Coils(128)); ... etc. */ } public void addEventListener(ModbusEventListener listener) { modbusEventListenerList.add(listener); } public boolean removeEventListener(ModbusEventListener listener) { return modbusEventListenerList.remove(listener); } @Override public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException, IllegalDataValueException { for (ModbusEventListener l : modbusEventListenerList) { l.onWriteToSingleHoldingRegister(offset, value); } super.writeHoldingRegister(offset, value); } @Override public void writeHoldingRegisterRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException { for (ModbusEventListener l : modbusEventListenerList) { l.onWriteToMultipleHoldingRegisters(offset, range.length, range); } super.writeHoldingRegisterRange(offset, range); } @Override public void writeCoil(int offset, boolean value) throws IllegalDataAddressException, IllegalDataValueException { for (ModbusEventListener l : modbusEventListenerList) { l.onWriteToSingleCoil(offset, value); } super.writeCoil(offset, value); } @Override public void writeCoilRange(int offset, boolean[] range) throws IllegalDataAddressException, IllegalDataValueException { for (ModbusEventListener l : modbusEventListenerList) { l.onWriteToMultipleCoils(offset, range.length, range); } super.writeCoilRange(offset, range); } }} 2)、Modbus-RTU
import com.intelligt.modbus.jlibmodbus.Modbus;import com.intelligt.modbus.jlibmodbus.data.DataHolder;import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters;import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;import com.intelligt.modbus.jlibmodbus.serial.SerialParameters;import com.intelligt.modbus.jlibmodbus.serial.SerialPort;import com.intelligt.modbus.jlibmodbus.serial.SerialPortException;import com.intelligt.modbus.jlibmodbus.slave.ModbusSlave;import com.intelligt.modbus.jlibmodbus.slave.ModbusSlaveFactory;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class JlibmodbusSlaveRtuWriter { public static void main(String[] args) throws SerialPortException, IllegalDataValueException, IllegalDataAddressException, ModbusIOException { SerialParameters serialParameters = new SerialParameters(); serialParameters.setDevice("COM1"); serialParameters.setBaudRate(SerialPort.BaudRate.getBaudRate(9600)); serialParameters.setDataBits(8); serialParameters.setStopBits(1); serialParameters.setParity(SerialPort.Parity.NONE); ModbusSlave modbusSlave = ModbusSlaveFactory.createModbusSlaveRTU(serialParameters); modbusSlave.setReadTimeout(2400); Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG); MyDataHolder myDataHolder = new MyDataHolder(); myDataHolder.addEventListener(new EventListeners() { @Override public void readHoldingRegister(int address) { System.out.println("使用03功能码读取保持寄存器的数据 address = " + address); } @Override public void readHoldingRegisterRange(int address, int quantity) { try { ModbusHoldingRegisters integers = updateHoldingRegisters(address, quantity); modbusSlave.getDataHolder().setHoldingRegisters(integers); }catch (Exception e){ e.printStackTrace(); } System.out.println("使用03功能码范围读取保持寄存器的数据 address = " + address + " 读取寄存器个数:" + quantity); } @Override public void writeHoldingRegister(int address, int value) throws IllegalDataValueException, IllegalDataAddressException { System.out.println("使用03功能码写入保持寄存器 address = " + address + " 值:" + value); } @Override public void writeHoldingRegisterRange(int address, int[] values) { System.out.println("使用03功能码批量写入保持寄存器 address = " + address + " 值:" + values.toString()); } }); modbusSlave.setDataHolder(myDataHolder); modbusSlave.setServerAddress(1); // ModbusHoldingRegisters mm = new ModbusHoldingRegisters(10); // mm.set(0, 1223); // mm.set(1, 321); // modbusSlave.getDataHolder().setHoldingRegisters(mm); modbusSlave.listen(); } public interface EventListeners{ void readHoldingRegister(int address); void readHoldingRegisterRange(int address, int quantity); void writeHoldingRegister(int address, int value) throws IllegalDataValueException, IllegalDataAddressException; void writeHoldingRegisterRange(int address, int[] values); } public static class MyDataHolder extends DataHolder{ final List eventListenerList = new ArrayList(); public void addEventListener(EventListeners eventListener){ eventListenerList.add(eventListener); } public boolean removeEventListener(EventListeners eventListener){ return eventListenerList.remove(eventListener); } @Override public int readHoldingRegister(int offset) throws IllegalDataAddressException { for (EventListeners e : eventListenerList){ e.readHoldingRegister(offset); } return super.readHoldingRegister(offset); } @Override public int[] readHoldingRegisterRange(int offset, int quantity) throws IllegalDataAddressException { for (EventListeners e : eventListenerList){ e.readHoldingRegisterRange(offset, quantity); } return super.readHoldingRegisterRange(offset, quantity); } @Override public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException, IllegalDataValueException { for (EventListeners e : eventListenerList){ e.writeHoldingRegister(offset, value); } super.writeHoldingRegister(offset, value); } @Override public void writeHoldingRegisterRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException { for (EventListeners e : eventListenerList){ e.writeHoldingRegisterRange(offset, range); } super.writeHoldingRegisterRange(offset, range); } } // 为从机设置03功能码对应的数值寄存器 public static ModbusHoldingRegisters updateHoldingRegisters(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException { List list = Arrays.asList(10.1f,20.3f,89.5f,73.353f); ModbusHoldingRegisters hr = new ModbusHoldingRegisters(10000); // 修改数值寄存器对应位置的值,第一个参数代表寄存器地址,第二个代表修改的数值 //hr.set有几个方法,根据自己要赋值的数据类型选择,此处示例的是赋值float类型,一个float是4个字节,32bit,对应2个寄存器所以i*2 for(int i=0;i
上一篇:小型播控服务器怎么用?