最近要从modbus总线上读写数据,用java来进行开发,前面用modbus4j进行过modbus tcp的通讯,这次是modbus rtu进行通讯,在这个过程中也踩了不少坑,做个记录
1、环境准备
(1)串口环境(使用virtual serial port driver,请自行下载)
添加虚拟串口对COM1和COM2
设备管理器中要能看到这2个端口
(2)modbus模拟器
使用ModSim模拟,ModSim下载地址
Connect Port1
新建
2、依赖的库
(1)modbus4j
(2)rxtx
Rxtx在Linux下配置RXTX和Windows下配置的操作不一样。
- Windows
将rxtxParallel.dll和rxtxSerial.dll文件放到JDK的jre/bin目录下(如D:\Java\jdk1.8.0_202\jre\bin)
- Linux
- 将librxtxSerial.so上传到/usr/local/lib下
- 修改配置文件(/etc/profile)添加export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
- 配置文件生效:source /etc/profile
- 保险起见,在/jre/bin和/jre/lib下也复制一份
- 同时复制RXTXcomm.jar到/jre/lib下
(3)freedomotic,需要用到modbus模块
访问路径:freedomotic/plugins/devices/modbus/src/main/java/com/freedomotic/plugins/devices/modbus
(4)seroUtils.jar
下载地址:https://download.csdn.net/download/james112496/85775225
(5)JDK1.8_202(最新的版本可能不支持,JDK的版本不能太高)
3、代码部分
modbus4j的SerialPortWrapper接口没有实现类,推荐使用Freedomotic中的三个类实现:
SerialPortWrapperImpl.java
SerialInputStream.java
SerialOutputStream.java
SerialInputStream.java
126行、127行必须进行如下修改
// System.arraycopy(readBuf, 0, buf, offset, length);
System.arraycopy(readBuf, 0, buf, offset, readBuf.length);
读取代码
public class ReadFromModbus {
// 从站地址
private final static int SLAVE_ADDRESS = 1;
//串行波特率
private final static int BAUD_RATE = 9600;
public static void main(String[] args) {
SerialPortWrapper serialParameters = new
SerialPortWrapperImpl("COM2", BAUD_RATE, 8, 1, 0, 0, 0);
/* 创建ModbusFactory工厂实例 */
ModbusFactory modbusFactory = new ModbusFactory();
/* 创建ModbusMaster实例 */
ModbusMaster master = modbusFactory.createRtuMaster(serialParameters);
/* 初始化 */
try {
master.init();
readHoldingRegistersTest(master, SLAVE_ADDRESS, 1, 9);
} catch (ModbusInitException e) {
e.printStackTrace();
} finally {
master.destroy();
}
}
/**
* 读取寄存器上的内容
*
* @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()));
short[] list = response.getShortData();
for (int i = 0; i < list.length; i++) {
System.out.print(list[i] + " ");
}
}
} 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();
}
}
4、源码下载
已实现modbus rtu的读写功能
下载地址:https://download.csdn.net/download/james112496/85775244