modbus RTU/TCP 串口通讯 读写数据(java)

第一次接触这个,网上资料也是比较少,搞了一天也终于搞定了,总结一下过程中遇到的一些问题,为后面的人做个警戒

1.首先需要使用RXTX的串口通讯包,还有modbus4J的包,具体如下,文章结尾我会附上资源的地址

基本上所有的问题都是在这个过程中遇到的,首先要把rxtxParallel.dll,rxtxSerial.dll,放到你的jdk的jre/bin文件夹下,RXTXcomm.jar放到jre/lib文件夹下,然后在你的项目中导入RXTXcomm.jar,具体操作步骤如下

  

然后选择你刚才jre/bin目录下的RXTXcomm.jar,点击保存,点击ok,就可以了

这个过程中会遇到几种bug,他们产生的原因和解决办法我会一一解答,具体如下

Native lib Version = RXTX-2.2-20081207 Cloudhopper Build rxtx.cloudhopper.net

Java lib Version = RXTX-2.1-7

WARNING: RXTX Version mismatch

Jar version = RXTX-2.1-7

native lib Version = RXTX-2.2-20081207 Cloudhopper Build rxtx.cloudhopper.net
这个bug是由于RXTX里面各种包版本不一样的问题,也就是上面截图里的几种包,解决方法就是更换包,换成同一个版本

第二个问题 报错信息如下

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000180004465, pid=25576, tid=30280
#
# JRE version: Java(TM) SE Runtime Environment (10.0.1+10) (build 10.0.1+10)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0.1+10, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C  [rxtxSerial.dll+0x4465]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\...l\hs_err_pid25576.log(保护隐私,路径已省略)
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

这个问题困扰了很久,最终原因很乌龙,是因为jdk版本不支持的问题,这里jdk的版本必须使用1.8-2以下的jdk版本才可以使用,我之前用的jdk9和jdk1.8-291全部都运行失败,

可能是这个开发包太老了导致这样的问题

第三个问题 modbus4J.jar,seroUtils.jar无法导入的问题,maven地址中找不到这两个包,我们可以把这个包下载下来之后,然后注册到本地仓库,具体步骤如下

  1、进入cmd命令界面

  2、输入指令如下:mvn install:install-file -Dfile=E:\CFCA\CFCA_xfraud_ml_01.jar -DgroupId=cfca.xfraud -DartifactId=ml -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true,其中

    Dfile为jar包文件路径

    DgroupId一般为jar开发组织的名称,也是坐标groupId

    DartifactId一般为jar名称,也是坐标 artifactId

    Dversion是版本号

    Dpackaging是打包类型

然后你进入到你的本地仓库就可以看到

复制到maven地址就可以

然后基本上就没什么问题了

具体代码如下

package cn.wu.demo.modbus4j;

import com.serotonin.io.serial.SerialParameters;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.msg.*;

import java.util.Arrays;

public class WriteToModbus1 {
    // MODBUS网络上从站地址
    private final static int SLAVE_ADDRESS = 1;


    public static void main(String[] args) throws Exception {
        SerialParameters serialParameters = new SerialParameters();
        // 设定MODBUS通讯的串行口
        serialParameters.setCommPortId("COM2");
        // 设定成无奇偶校验
        serialParameters.setParity(0
        );
        // 设定成数据位是8位
        serialParameters.setDataBits(8);
        // 设定为1个停止位
        serialParameters.setStopBits(1);
        serialParameters.setPortOwnerName("COM2");
        // 串行口上的波特率
        serialParameters.setBaudRate(9600);
        ModbusFactory modbusFactory = new ModbusFactory();
        ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);
        try {
            master.init();
            readDiscreteInputTest(master, 1, 0, 3);
            writeRegistersTest(master, 1, 0, new short[] { 0x31, 0xb, 0xc, 0xd, 0xe,
                    0x9, 0x8, 0x7, 0x6 });
            readHoldingRegistersTest(master, 1, 0, 3);
        } finally {
            master.destroy();
        }
    }

    /**
     * 读开关量型的输入信号
     *
     * @param master
     *            主站
     * @param slaveId
     *            从站地址
     * @param start
     *            起始偏移量
     * @param len
     *            待读的开关量的个数
     */
    private static void readDiscreteInputTest(ModbusMaster master, int slaveId, int start, int len) {
        try {
            ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);
            ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(Arrays.toString(response.getBooleanData()));
        } catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读保持寄存器上的内容
     *
     * @param master
     *            主站
     * @param slaveId
     *            从站地址
     * @param start
     *            起始地址的偏移量
     * @param len
     *            待读寄存器的个数
     */
    private static void readHoldingRegistersTest(ModbusMaster master, int slaveId, int start,
            int len) {
        try {
            ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start,
                    len);
            ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master
                    .send(request);
            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println(Arrays.toString(response.getShortData()));
        } catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }

    /**
     * 批量写数据到保持寄存器
     *
     * @param master
     *            主站
     * @param slaveId
     *            从站地址
     * @param start
     *            起始地址的偏移量
     * @param values
     *            待写数据
     */
    public static void writeRegistersTest(ModbusMaster master, int slaveId, int start,
            short[] values) {
        try {
            WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
            WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
            if (response.isException())
                System.out.println("Exception response: message=" + response.getExceptionMessage());
            else
                System.out.println("Success");
        } catch (ModbusTransportException e) {
            e.printStackTrace();
        }
    }
}

pom包如下

<repositories>
    <repository>
        <id>alimaven</id>
        <name>aliyun maven</name>
        <url>
            http://maven.aliyun.com/nexus/content/groups/public/
        </url>
    </repository>
    <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>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.5.4</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
//这个是modbus包,我下载jar包下来,注册到本地仓库的时候就随便起了个名字
    <dependency>
        <groupId>zyf</groupId>
        <artifactId>modbus</artifactId>
        <version>1.0.0</version>
    </dependency>
//这个是串口用的包,也是随便起了个名字
    <dependency>
        <groupId>zyf1</groupId>
        <artifactId>modbus</artifactId>
        <version>1.0.0</version>
    </dependency>

    <!--<dependency>-->
        <!--<groupId>com.infiniteautomation</groupId>-->
        <!--<artifactId>modbus4j</artifactId>-->
        <!--<version>3.0.3</version>-->
    <!--</dependency>-->


    <dependency>
        <groupId>com.github.zengfr</groupId>
        <artifactId>easymodbus4j</artifactId>
        <version>0.0.1</version>
    </dependency>

    <dependency>
        <groupId>com.twitter.serial</groupId>
        <artifactId>serial</artifactId>
        <version>0.1.6</version>
    </dependency>
    <dependency>
        <groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
        <artifactId>rxtxcomm</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>compile</scope>
    </dependency>

</dependencies>

相关包下载地址modbus.rarjavamodbusrtu,tcp通讯源码-Java文档类资源-CSDN下载没积分的私我要,最近好多要了资源还问个不停的,太麻烦了,需要完整项目的也可以找我要哈

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 36
    评论
modbus是一种通信协议,常用于工业自动化领域中的设备之间的数据传输。在实际应用中,可以使用C语言编写程序来实现modbus RTUmodbus TCP通信。 modbus RTU通信示例中,可以先设置串口参数,如波特率、数据位等。然后使用串口读写函数来与modbus设备进行通信。例如,可以使用C语言中的open、read和write函数来打开串口、读取数据和写入数据。 以下是一个modbus RTU通信实例的C代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> int main() { int fd; struct termios serial; fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY); if (fd == -1) { perror("open"); return -1; } memset(&serial, 0, sizeof(serial)); serial.c_iflag = 0; serial.c_oflag = 0; serial.c_cflag = CS8 | CREAD | CLOCAL; serial.c_lflag = 0; serial.c_cc[VMIN] = 1; serial.c_cc[VTIME] = 5; cfsetospeed(&serial, B9600); cfsetispeed(&serial, B9600); if (tcsetattr(fd, TCSANOW, &serial) == -1) { perror("tcsetattr"); return -1; } // 使用read和write函数与modbus设备进行通信,具体的读写操作需要根据modbus协议进行解析和封装。 // ... close(fd); return 0; } ``` 而modbus TCP通信则是在基于TCP/IP的网络中实现的,需要使用套接字编程来实现。以下是一个modbus TCP通信实例的C代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main() { int sockfd; struct sockaddr_in serveraddr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); return -1; } memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(502); inet_pton(AF_INET, "192.168.1.1", &(serveraddr.sin_addr)); if (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1) { perror("connect"); return -1; } // 使用send和recv函数与modbus设备进行通信,具体的读写操作需要根据modbus协议进行解析和封装。 // ... close(sockfd); return 0; } ``` 以上是实现modbus RTUmodbus TCP通信的简单示例,具体的读写操作和数据解析需要根据实际需求和modbus协议进行相应的处理。
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值