上面我们写了一篇关于modbus-tcp的文章,这一篇我们主要将关于modbus-rtu的对接方式,好了,废话不多说,直接开搞。

一、环境准备

1.下载Virtual Serial Port Driver 6.9,使用此工具模拟com串口
链接:https://pan.baidu.com/s/1mBoqHZ4LzaSuY7EFHEjyxQ
提取码:7qku

java 模拟ie java 模拟modbus slave_modbus

2.下载modscan32,其中应该会包含modscan32(主机)及modsim32(从机),我们后续会使用modsim32模拟从机。
下载地址或自行百度搜索(网上资源还是很多的):

java 模拟ie java 模拟modbus slave_串口通信_02

3.java环境准备,此处我们使用的是jdk1.8

二、代码编写

2.1 Virtual Serial Port Driver准备

首先我们先使用Virtual Serial Port Driver打开两个串口COM7,COM8,入下图所示

java 模拟ie java 模拟modbus slave_rtu_03

2.2 modsim准备

然后我们打开modsim,开始模拟准备从机数据,操作流程入下图所示。

1.连接设置->连接->端口7(因为我们刚才添加的com7和com8,我们使用com7作为从机口,com8一会我们java代码使用)

java 模拟ie java 模拟modbus slave_java_04


2.文件->新建

java 模拟ie java 模拟modbus slave_串口通信_05

3.配置从机相关数据

java 模拟ie java 模拟modbus slave_java 模拟ie_06

2.3 编写Java代码

上述准备工作都做完了,我们开始编写Java主机代码rtu解析


1.创建一个maven项目

2.创建lib文件夹在maven项目中,并添加modbus4J.jar、RXTXcomm.jar、seroUtils.jar三个jar包

java 模拟ie java 模拟modbus slave_串口通信_07


3.添加maven依赖

<dependencies>
        <dependency>
            <groupId>com.beyondli</groupId>
            <artifactId>modbus4j</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/modbus4J.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.beyondli</groupId>
            <artifactId>sero</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/seroUtils.jar</systemPath>
        </dependency>

        <dependency>
            <groupId>com.beyondli</groupId>
            <artifactId>rxtx</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/RXTXcomm.jar</systemPath>
        </dependency>
    </dependencies>

java 模拟ie java 模拟modbus slave_rtu_08

4.jre中添加rxtxParallel.dll和rxtxSerial.dll文件

首先,我们找到我们的jdk环境安装地址进入到对应的jre文件夹中,此地址每个同学需要根据自己的安装目录进行调整。以下是我的目录结构

rxtxSerial.dll文件我们放到jdk的jre/bin文件夹下

java 模拟ie java 模拟modbus slave_rtu_09

rxtxParallel.dll文件我们放到jre\lib\ext文件夹下

java 模拟ie java 模拟modbus slave_java_10

5.编写Java代码(主机)获取从机信息

读取从机和修改写入从机的对应方法均在下面的代码中,同学们可以自行阅读注释,根据自行业务进行调整。

package com.beyondli;


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 ModbusPollRTUTest {


	public static void main(String[] args) {
		SerialParameters serialParameters = new SerialParameters();
		// 设定MODBUS通讯的串行口
		serialParameters.setCommPortId("COM8");
		// 设定成无奇偶校验
		serialParameters.setParity(0);
		// 设定成数据位是8位
		serialParameters.setDataBits(8);
		// 设定为1个停止位
		serialParameters.setStopBits(1);
		// 设定端口名称
		serialParameters.setPortOwnerName("Numb nuts");
		// 设定端口波特率
		serialParameters.setBaudRate(19200);

		// 创建ModbusFactory工厂实例
		ModbusFactory modbusFactory = new ModbusFactory();
		// 创建ModbusMaster实例
		ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);


		// 初始化
		try {
			master.init();

			//写入从站3号位为7166
			writeHoldingRegistersTest(master,1,2,7166);

			//读取从站信息
			while (true) {
				readHoldingRegistersTest(master,1,0,5);
				Thread.sleep(1000);
			}



		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			master.destroy();
		}

	}


	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()));
				short[] list = response.getShortData();
				for(int i = 0; i < list.length; i++){
					System.out.println(list[i] + " ");
				}
				/*
				System.out.println();

				int hight = (list[3] - 4000) /160;
				if(hight <= 0){
					System.out.println("水位高度为:0CM");
				}else{
					System.out.println("水位高度为:" + (hight + 13.5) + "CM");
				}*/

			}
		} catch (ModbusTransportException e) {
			e.printStackTrace();
		}
	}


	private static void writeHoldingRegistersTest(ModbusMaster master,
												 int slaveId, int start, int value) {
		try {
			/*
			value.replace(" ", ""); //去除所有空格,包括首尾、中间
			//先把Stirng数据转成char数组
			char[] dataChar = value.toCharArray();
			//创建一个short数组,大小为参数的长度
			short[] dataShort = new short[value.length()];
			//循环dataChar数组,把dataChar一个一个存到short中
			for (int i = 0; i < dataChar.length; i++) {
				dataShort[i] = (short) dataChar[i];
			}*/

			WriteRegisterRequest request = new WriteRegisterRequest(
					slaveId, start, value);
			WriteRegisterResponse  response = (WriteRegisterResponse) master
					.send(request);

			if (response.isException()){
				System.out.println("Exception response: message=" + response.getExceptionMessage());
			}
			else {
				System.out.println("Success");
			}
		} catch (ModbusTransportException e) {
			e.printStackTrace();
		}
	}

}

最终效果入下图所示

java 模拟ie java 模拟modbus slave_串口通信_11


java 模拟ie java 模拟modbus slave_java 模拟ie_12