1、简介
- Modbus4j 支持 Modbus 的多种传输模式,包括 TCP、RTU、ASCII 等,能够适应不同的网络环境和设备需求。例如,在工业自动化场景中,可能会遇到通过串口(使用 RTU 模式)或以太网(使用 TCP 模式)连接的设备,Modbus4j 可以灵活处理这些不同的通信方式。
2、通信过程中的重要概念
- 主站(Master)和从站(Slave):
- 主站:发起 Modbus 请求的设备,例如监控计算机或控制器,负责发送命令(如读取或写入数据)。
- 从站:响应主站请求的设备,例如传感器、PLC 等,它们根据主站的请求进行操作,如提供数据或接收写入的数据。
- 功能码(Function Codes):
- Modbus 协议定义了多种功能码,用于不同的操作,例如读取线圈状态、读取输入寄存器、写入单个线圈等。Modbus4j 提供了相应的 API 来使用这些功能码,方便开发者调用。
3、pom文件
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.0.4</version>
</dependency>
4、创建slave从站
package com.example.demo.modbus;
import com.serotonin.modbus4j.*;
import com.serotonin.modbus4j.exception.IllegalDataAddressException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
public class ModbusSlaveExample {
public static void main(String[] args) {
// 创建 Modbus 工厂
ModbusFactory modbusFactory = new ModbusFactory();
// 设置 IP 参数
IpParameters ipParameters = new IpParameters();
ipParameters.setHost("127.0.0.1");
ipParameters.setPort(502);
// 创建 Modbus 从站集合
ModbusSlaveSet slaveSet = modbusFactory.createTcpSlave(false);
try {
// 添加从站
int slaveId = 1;
ProcessImage processImage = new ProcessImage() {
@Override
public int getSlaveId() {
return slaveId;
}
@Override
public boolean getCoil(int offset) throws IllegalDataAddressException {
return offset % 2 == 0;
}
@Override
public void setCoil(int offset, boolean value) {
}
@Override
public void writeCoil(int offset, boolean value) throws IllegalDataAddressException {
}
@Override
public boolean getInput(int offset) throws IllegalDataAddressException {
return offset % 2 == 0;
}
@Override
public void setInput(int offset, boolean value) {
}
@Override
public short getHoldingRegister(int offset) throws IllegalDataAddressException {
return (short) (offset % 2);
}
@Override
public void setHoldingRegister(int offset, short value) {
}
@Override
public void writeHoldingRegister(int offset, short value) throws IllegalDataAddressException {
}
@Override
public short getInputRegister(int offset) throws IllegalDataAddressException {
return (short) (offset % 2);
}
@Override
public void setInputRegister(int offset, short value) {
}
@Override
public byte getExceptionStatus() {
return 0;
}
@Override
public byte[] getReportSlaveIdData() {
return new byte[0];
}
};
slaveSet.addProcessImage(processImage);
// 初始化从站
slaveSet.start();
} catch (ModbusInitException e) {
e.printStackTrace();
} finally {
// 关闭从站
slaveSet.stop();
}
}
}
5、创建master主站读取数据
package com.example.demo.modbus;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
public class ModbusMasterExample {
public static void main(String[] args) {
// 创建 Modbus 工厂
ModbusFactory modbusFactory = new ModbusFactory();
// 设置 IP 参数
IpParameters ipParameters = new IpParameters();
ipParameters.setHost("127.0.0.1"); // 目标设备的 IP 地址
ipParameters.setPort(502); // Modbus TCP 端口号,默认为 502
// 创建 Modbus TCP 主站
ModbusMaster master = modbusFactory.createTcpMaster(ipParameters, false);
try {
// 初始化主站
master.init();
// 读取从站的保持寄存器
int slaveId = 1; // 从站地址
int startOffset = 0; // 起始寄存器地址
int numberOfRegisters = 10; // 要读取的寄存器数量
// 创建读取请求
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startOffset, numberOfRegisters);
// 发送请求并获取响应
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
if (response.isException()) {
System.out.println("Exception response: " + response.getExceptionMessage());
} else {
// 获取数据
short[] registerData = response.getShortData();
for (int i = 0; i < registerData.length; i++) {
System.out.println("Register " + (startOffset + i) + " value: " + registerData[i]);
}
}
} catch (ModbusInitException | ModbusTransportException e) {
e.printStackTrace();
} finally {
// 关闭主站
master.destroy();
}
}
}
5、工具
modscan(主站/客户端)、modsim(从站/服务端)