当前位置: 代码网 > it编程>编程语言>Java > java如何通过modbus4j实现modbus TCP通讯

java如何通过modbus4j实现modbus TCP通讯

2025年07月20日 Java 我要评论
modbus通信协议主要分为三个子协议:rtuasciitcpmodbus rtu:——传输的是字节数组(bit[])通信:读写输出:可以读写输入:只能读存储区:输出线圈、输入

modbus通信协议

主要分为三个子协议:

  • rtu
  • ascii
  • tcp

modbus rtu:——传输的是字节数组(bit[])

  • 通信:读写
  • 输出:可以读写
  • 输入:只能读

存储区:输出线圈、输入线圈、输出寄存器、输入寄存器

线圈:代表一个布尔量、最小单位是一个布尔(1或者0),

寄存器:一个寄存器代表16个最小单位,主要用于存储数据

存储区代号:

输出线圈: 0(代号)

  • 00001-09999(标准存储区地址范围)
  • 000001-065536(扩展存储区地址范围)

输入线圈:1

  • 10001-19999

输出寄存器:4

  • 40001-49999

输入寄存器:3

  • 30001-39999

存储区范围:5位和6位

  • 5位:标准地址-y xxxx
  • 6位:扩展地址-y xxxxx

功能代码:

验证4个常用功能码,仿真软件上面有f=01,f=02,f=03和f=04来显示

  • 0x01:读线圈
  • 0x02:读离散量输入
  • 0x03:读保持寄存器
  • 0x04:读输入寄存器

测试使用modbus slave(下载) 模拟

  • saveid:看资料"从站在modbus总线上可以有多个",仿真软件就能模拟一个从站,就是id=1,当然可以修改成id=2
  • 功能码:4个功能码,对应写4个方法,,仿真软件上的f=1,或者f=2,3,4
  • addr:一开始看代码4个方法addr都是从0开始,是否重复?答案是:4个功能码表示4个区域或者设备,addr表示各自区域的地址编号。

connection设置:设置连接参数

地址设置: f8 ,可以通过setup或者右击点位的

设置不同存储区

读取从站

代码实现

1、依赖下载

  • 阿里云不能直接下载
<!-- 若想引用modbus4j需要引入下列repository id:ias-snapshots id:ias-releases 两个 ,使用默认仓库下载,不要使用阿里云仓库-->
    <repositories>
	    <repository>
	        <releases>
	            <enabled>false</enabled>
	        </releases>
	        <snapshots>
	            <enabled>true</enabled>
	        </snapshots>
	        <id>ias-snapshots</id>
	        <name>infinite automation snapshot repository</name>
	        <url>https://maven.mangoautomation.net/repository/ias-snapshot/</url>
	    </repository>
	    <repository>
	        <releases>
	            <enabled>true</enabled>
	        </releases>
	        <snapshots>
	            <enabled>false</enabled>
	        </snapshots>
	        <id>ias-releases</id>
	        <name>infinite automation release repository</name>
	        <url>https://maven.mangoautomation.net/repository/ias-release/</url>
	    </repository>
	</repositories>
	
    <dependencies>
		 <dependency>
		    <groupid>junit</groupid>
		    <artifactid>junit</artifactid>
		    <version>4.13-beta-3</version>
		    <scope>test</scope>
		</dependency>
		<dependency>
		    <groupid>com.infiniteautomation</groupid>
		    <artifactid>modbus4j</artifactid>
		    <version>3.0.3</version>
		</dependency>
		
		<dependency>
		    <groupid>org.apache.commons</groupid>
		    <artifactid>commons-lang3</artifactid>
		    <version>3.9</version>
		</dependency>
    </dependencies>

2、测试读取

  • 读取04(寄存器)
import com.intelligt.modbus.jlibmodbus.modbus;
import com.intelligt.modbus.jlibmodbus.exception.modbusioexception;
import com.intelligt.modbus.jlibmodbus.master.modbusmaster;
import com.intelligt.modbus.jlibmodbus.master.modbusmasterfactory;
import com.intelligt.modbus.jlibmodbus.tcp.tcpparameters;
import java.net.inetaddress;
import java.net.unknownhostexception;

public class testmodbus {
    public static void main(string[] args) throws unknownhostexception {
            // 设置主机tcp参数
            tcpparameters tcpparameters = new tcpparameters();

            // 设置tcp的ip地址
            inetaddress address = inetaddress.getbyname("127.0.0.1");
            // tcp参数设置ip地址
            tcpparameters.sethost(address);

            // tcp设置长连接
            tcpparameters.setkeepalive(true);
            // tcp设置端口,这里设置是默认端口502
            tcpparameters.setport(modbus.tcp_port);

            // 创建一个主机
            modbusmaster master = modbusmasterfactory.createmodbusmastertcp(tcpparameters);
            modbus.setautoincrementtransactionid(true);

            int slaveid = 1;//从机地址
            int offset = 0;//寄存器读取开始地址
            int quantity = 10;//读取的寄存器数量

            try {
            if (!master.isconnected()){
                master.connect(); //开启连接
            }
                // 读取对应从机的数据,readinputregisters读取的写寄存器,功能码04
            int[] registervalues4 = master.readinputregisters(slaveid,offset,quantity);

            for (int value : registervalues4){
                system.out.println("address:"+offset++ +",value:"+value);
            }
            }catch (exception e){
                e.printstacktrace();
            }finally {
                try {
                    master.disconnect();
                } catch (modbusioexception e) {
                    e.printstacktrace();
                }
            }
    }
}

3、读取工具类

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;

public class modbus4jreadutils {

    static modbusfactory modbusfactory;
    static {
        if (modbusfactory == null){
            modbusfactory = new modbusfactory();
        }
    }
    /*** 
     * 初始化连接
     * @return modbusmaster 
     */
    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.crea
        modbusmaster master = modbusfactory.createtcpmaster(params,false);
        master.init();
        return master;
    }

    /***
     *  读取[01 coil status 0x]类型 开关数据
     * @author zhengfuping
     * @param slaveid 从站编号
     * @param offset 偏移位置
     * @return boolean
     */
    public static boolean readcoilstatus(int slaveid,int offset) throws modbusinitexception, errorresponseexception, modbustransportexception {
        baselocator<boolean> loc = baselocator.coilstatus(slaveid,offset);
        boolean value = getmaster().getvalue(loc);
        return value;
    }


    /**
     * 读取[02 input status 1x]类型 开关数据
     *
     * @param slaveid 从站编号
     * @param offset 偏移位
     * @return
     */
    public static boolean readinputstatus(int slaveid, int offset)
            throws modbustransportexception, errorresponseexception, modbusinitexception {
        // 02 input status
        baselocator<boolean> loc = baselocator.inputstatus(slaveid, offset);
        boolean value = getmaster().getvalue(loc);
        return value;
    }

    /**
     * 读取[03 holding register类型 2x]模拟量数据
     * @param slaveid
     * @param offset 位置
     * @param datatype 数据类型,来自com.serotonin.modbus4j.code.datatype
     */
    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]类型 模拟量数据
     */
    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;
    }

//    批量读取
public static void batchread(integer count) throws modbusinitexception, errorresponseexception, modbustransportexception {
    batchread<integer> batch = new batchread<integer>();

    for (int i = 0; i <= count; i++) {
        batch.addlocator(i,baselocator.holdingregister(1,i, datatype.two_byte_int_signed));
    }

    modbusmaster master =getmaster();

    batch.setcontiguousrequests(false);
    batchresults<integer> results = master.send(batch);
    for (int i = 0; i <= count; i++) {
        system.err.println(results.getvalue(i));
    }
}

    public static void main(string[] args) {
        try {
            // 01测试
            boolean v011 = readcoilstatus(1,1);
            boolean v012 = readcoilstatus(1,2);
            boolean v013 = readcoilstatus(1,3);

            system.out.println("v011:" + v011);
            system.out.println("v012:" + v012);
            system.out.println("v013:" + v013);
            // 02测试
            boolean v021 = readinputstatus(1, 1);
            boolean v022 = readinputstatus(1, 2);
            boolean v023 = readinputstatus(1, 3);
            system.out.println("v021:" + v021);
            system.out.println("v022:" + v022);
            system.out.println("v023:" + v023);

            // 03测试
            number v031 = readholdingregister(1, 1, datatype.two_byte_int_signed);//signed
            number v032 = readholdingregister(1, 2, datatype.two_byte_int_signed);// 同上
            system.out.println("v031:" + v031);
            system.out.println("v032:" + v032);

            // 04测试
            number v041 = readinputregisters(1, 1, datatype.two_byte_int_signed);//
            number v042 = readinputregisters(1, 2, datatype.two_byte_int_signed);//
            system.out.println("v041:" + v041);
            system.out.println("v042:" + v042);

//            批量读取
            batchread(9);
        } catch (exception e) {
            e.printstacktrace();
        }
    }
}

读取结果:

4、写入工具类

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.*;
import org.apache.commons.logging.log;
import org.apache.commons.logging.logfactory;

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 值
     */
    public static boolean writecoil(int slaveid, int writeoffset, boolean writevalue)
            throws modbustransportexception, modbusinitexception {
        // 获取master
        modbusmaster 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
     * @param startoffset  开始位置
     * @param bdata 写入的数据
     * @return 是否写入成功
     */
    public static boolean writecoils(int slaveid, int startoffset, boolean[] bdata)
            throws modbustransportexception, modbusinitexception {
        // 获取master
        modbusmaster 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
     */
    public static boolean writeregister(int slaveid, int writeoffset, short writevalue)
            throws modbustransportexception, modbusinitexception {
        // 获取master
        modbusmaster 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
     * @param startoffset 起始位置偏移量值
     * @param sdata 写入的数据
     */
    public static boolean writeregisters(int slaveid, int startoffset, short[] sdata)
            throws modbustransportexception, modbusinitexception {
        // 获取master
        modbusmaster 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 datatype com.serotonin.modbus4j.code.datatype
     */
    public static void writeholdingregister(int slaveid, int offset, number value, int datatype)
            throws modbustransportexception, errorresponseexception, modbusinitexception {
        // 获取master
        modbusmaster tcpmaster = getmaster();
        // 类型
        baselocator<number> locator = baselocator.holdingregister(slaveid, offset, datatype);
        tcpmaster.setvalue(locator, value);
    }

    public static void main(string[] args) {
        try {
//             测试01  单个写入(0x)
			boolean t01 = writecoil(1, 0, true);
			system.out.println("t01:" + t01);

//             测试02  批量写入(0x)
			boolean t02 = writecoils(1, 0, new boolean[] { true, false, true });
			system.out.println("t02:" + t02);

//             测试03  单个写入(4x)
			short v = -3;
			boolean t03 = writeregister(1, 0, v);
			system.out.println("t03:" + t03);
//             测试04  批量写入(4x)
			boolean t04 = writeregisters(1, 0, new short[] { -309, 390, 91 });
			system.out.println("t04:" + t04);
            //写模拟量
            writeholdingregister(1,8, 100, datatype.two_byte_int_signed);
            
        } catch (exception e) {
            e.printstacktrace();
        }
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com