小工具知识网

当前位置: 首页 > 行业知识 > 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

上一篇:小型播控服务器怎么用?

下一篇:Win10电脑性能一目了然,配置查看指南