上个文章写了snmp,这回写写modbus,仍然研究不深入,毕竟只是应付工作,更多的东西只能留到以后有机会去研究了。
使用modbus,肯定是需要配相关环境的,首先是rxtxSerial.dll和rxtxParallel.dll两个文件,将这两个文件放到jdk中的jre的bin目录下,否则运行时会报错。
其次是导入jar包,modbus4j.jar、RXTXcomm.jar和seroUtils.jar这三个是必须的。
最后就是模拟器了,因为编程过程中很少有机会用真正的机器去给你玩,所以模拟器也是必不可少,ModbusSlave和ModbusPoll应该能满足测试需要了,这样TCP传输是没问题了,但是如果是RTU传输,还需要一个虚拟串口软件,这里使用VSPD。
准备活动结束,接下来是编码,首先用ModbusSlave创建一个TCP/IP的Slave,然后用下面的代码来修改它的指标值
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.ModbusRequest;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
public class ModbusTcp {
public static void main(String[] args) {
IpParameters params = new IpParameters();
params.setHost("127.0.0.1");
params.setPort(502);
ModbusFactory factory = new ModbusFactory();
ModbusMaster master= factory.createTcpMaster(params, true);
try {
master.init();
ModbusRequest request;
try {
request = new WriteRegisterRequest(1, 0,
26);
WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
if (response.isException()) {
String exceptionCode = null;
}
// String value = Arrays.toString(response.getShortData());
// System.out.println(value);
} catch (ModbusTransportException e) {
e.printStackTrace();
}
} catch (ModbusInitException e) {
e.printStackTrace();
}
}
}
TCP/IP的还算比较简单,接下来是RTU,这次要用到虚拟串口了,公司网传不了图,也是醉了。总之就是创建一对虚拟串口,比如我是COM2和COM3,程序用COM2,Slave用COM3,Mode用RTU,程序和Slave两端的参数设置一定要一致。
import java.util.Arrays;
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.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
public class ModbusRTU {
private ModbusFactory factory = new ModbusFactory();
private ModbusMaster master = null;
public void init() {
SerialParameters params = new SerialParameters();
try {
// 设定 MODBUS 通讯的串行口
params.setCommPortId("COM2");
// 设定成无奇偶校验
params.setParity(2);
// 设定成数据位是 8 位
params.setDataBits(8);
// 设定为 1 个停止位
params.setStopBits(1);
// 串行口上的波特率
params.setBaudRate(19200);
master = factory.createRtuMaster(params);
master.setRetries(0);
master.init();
System.out.println(master.isInitialized());
System.out.println(master.hashCode());
} catch (Exception e) {
e.printStackTrace();
}
}
public void destroy() {
this.master.destroy();
}
/**
* 读保持寄存器上的内容
*
* @param master
* 主站
* @param slaveId
* 从站地址
* @param start
* 起始地址的偏移量
* @param len
* 待读寄存器的个数
*/
public void readHoldingRegisters(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.getData()));
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public void WriteRegistersRequest(int slaveId, int startOffset,short[] sdata) {
WriteRegistersRequest request = null;
WriteRegistersResponse response = null;
try {
request = new WriteRegistersRequest(slaveId, startOffset, sdata);
response = (WriteRegistersResponse) master.send(request);
if (response.isException()) {
System.out.println(response.getExceptionCode());
System.out.println(response.getExceptionMessage());
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
short[] sdata = {1,2,3,4,5};
ModbusRTU rtu = new ModbusRTU();
rtu.init();
rtu.WriteRegistersRequest(1,0,sdata);
rtu.readHoldingRegisters(1, 0, 8);
rtu.destroy();
}
}