引入jar包
<!--modbus4j-->
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.clojars.frozenlock/sero-utils -->
<dependency>
<groupId>org.clojars.frozenlock</groupId>
<artifactId>sero-utils</artifactId>
<version>1.1.5</version>
</dependency>
SerialInputStream.java
package com.docmgr.workstation.communication.protocol.modbus;
import jssc.SerialPort;
import java.io.IOException;
import java.io.InputStream;
/**
* Class that wraps a {@link SerialPort} to provide {@link InputStream}
* functionality. This stream also provides support for performing blocking
* reads with timeouts.
* <br>
* It is instantiated by passing the constructor a {@link SerialPort} instance.
* Do not create multiple streams for the same serial port unless you implement
* your own synchronization.
*
* @author Charles Hache <chalz@member.fsf.org>
*
* Attribution: https://github.com/therealchalz/java-simple-serial-connector
*
*/
public class SerialInputStream extends InputStream {
private SerialPort serialPort;
private int defaultTimeout = 0;
/**
* Instantiates a SerialInputStream for the given {@link SerialPort} Do not
* create multiple streams for the same serial port unless you implement
* your own synchronization.
*
* @param sp The serial port to stream.
*/
public SerialInputStream(SerialPort sp) {
serialPort = sp;
}
/**
* Set the default timeout (ms) of this SerialInputStream. This affects
* subsequent calls to {@link #read()}, {@link #(int[])}, and
* {@link #(int[], int, int)} The default timeout can be 'unset'
* by setting it to 0.
*
* @param time The timeout in milliseconds.
*/
public void setTimeout(int time) {
defaultTimeout = time;
}
/**
* Reads the next byte from the port. If the timeout of this stream has been
* set, then this method blocks until data is available or until the timeout
* has been hit. If the timeout is not set or has been set to 0, then this
* method blocks indefinitely.
*/
@Override
public int read() throws IOException {
return read(defaultTimeout);
}
/**
* The same contract as {@link #read()}, except overrides this stream's
* default timeout with the given timeout in milliseconds.
*
* @param timeout The timeout in milliseconds.
* @return The read byte.
* @throws IOException On serial port error or timeout
*/
public int read(int timeout) throws IOException {
byte[] buf = new byte[1];
try {
if (timeout > 0) {
buf = serialPort.readBytes(1, timeout);
} else {
buf = serialPort.readBytes(1);
}
return buf[0];
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Non-blocking read of up to buf.length bytes from the stream. This call
* behaves as read(buf, 0, buf.length) would.
*
* @param buf The buffer to fill.
* @return The number of bytes read, which can be 0.
* @throws IOException on error.
*/
@Override
public int read(byte[] buf) throws IOException {
return read(buf, 0, buf.length);
}
/**
* Non-blocking read of up to length bytes from the stream. This method
* returns what is immediately available in the input buffer.
*
* @param buf The buffer to fill.
* @param offset The offset into the buffer to start copying data.
* @param length The maximum number of bytes to read.
* @return The actual number of bytes read, which can be 0.
* @throws IOException on error.
*/
@Override
public int read(byte[] buf, int offset, int length) throws IOException {
if (buf.length < offset + length) {
length = buf.length - offset;
}
int available = this.available();
if (available > length) {
available = length;
}
try {
byte[] readBuf = serialPort.readBytes(available);
System.arraycopy(readBuf, 0, buf, offset, length);
return readBuf.length;
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Blocks until buf.length bytes are read, an error occurs, or the default
* timeout is hit (if specified). This behaves as blockingRead(buf, 0,
* buf.length) would.
*
* @param buf The buffer to fill with data.
* @return The number of bytes read.
* @throws IOException On error or timeout.
*/
public int blockingRead(byte[] buf) throws IOException {
return blockingRead(buf, 0, buf.length, defaultTimeout);
}
/**
* The same contract as {@link #blockingRead(byte[])} except overrides this
* stream's default timeout with the given one.
*
* @param buf The buffer to fill.
* @param timeout The timeout in milliseconds.
* @return The number of bytes read.
* @throws IOException On error or timeout.
*/
public int blockingRead(byte[] buf, int timeout) throws IOException {
return blockingRead(buf, 0, buf.length, timeout);
}
/**
* Blocks until length bytes are read, an error occurs, or the default
* timeout is hit (if specified). Saves the data into the given buffer at
* the specified offset. If the stream's timeout is not set, behaves as
* {@link #read(byte[], int, int)} would.
*
* @param buf The buffer to fill.
* @param offset The offset in buffer to save the data.
* @param length The number of bytes to read.
* @return the number of bytes read.
* @throws IOException on error or timeout.
*/
public int blockingRead(byte[] buf, int offset, int length) throws IOException {
return blockingRead(buf, offset, length, defaultTimeout);
}
/**
* The same contract as {@link #blockingRead(byte[], int, int)} except
* overrides this stream's default timeout with the given one.
*
* @param buf The buffer to fill.
* @param offset Offset in the buffer to start saving data.
* @param length The number of bytes to read.
* @param timeout The timeout in milliseconds.
* @return The number of bytes read.
* @throws IOException On error or timeout.
*/
public int blockingRead(byte[] buf, int offset, int length, int timeout) throws IOException {
if (buf.length < offset + length) {
throw new IOException("Not enough buffer space for serial data");
}
if (timeout < 1) {
return read(buf, offset, length);
}
try {
byte[] readBuf = serialPort.readBytes(length, timeout);
System.arraycopy(readBuf, 0, buf, offset, length);
return readBuf.length;
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public int available() throws IOException {
int ret;
try {
ret = serialPort.getInputBufferBytesCount();
if (ret >= 0) {
return ret;
}
throw new IOException("Error checking available bytes from the serial port.");
} catch (Exception e) {
throw new IOException("Error checking available bytes from the serial port.");
}
}
}
SerialOutputStream.java
package com.docmgr.workstation.communication.protocol.modbus; /**
*
* Copyright (c) 2009-2020 Freedomotic Team http://www.freedomotic-iot.com
*
* This file is part of Freedomotic
*
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
import jssc.SerialPort;
import jssc.SerialPortException;
import java.io.IOException;
import java.io.OutputStream;
/**
* Class that wraps a {@link SerialPort} to provide {@link OutputStream}
* functionality.
* <br>
* It is instantiated by passing the constructor a {@link SerialPort} instance.
* Do not create multiple streams for the same serial port unless you implement
* your own synchronization.
*
* @author Charles Hache <chalz@member.fsf.org>
*
* Attribution: https://github.com/therealchalz/java-simple-serial-connector
*
*/
public class SerialOutputStream extends OutputStream {
SerialPort serialPort;
/**
* Instantiates a SerialOutputStream for the given {@link SerialPort} Do not
* create multiple streams for the same serial port unless you implement
* your own synchronization.
*
* @param sp The serial port to stream.
*/
public SerialOutputStream(SerialPort sp) {
serialPort = sp;
}
@Override
public void write(int b) throws IOException {
try {
serialPort.writeInt(b);
} catch (SerialPortException e) {
throw new IOException(e);
}
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
byte[] buffer = new byte[len];
System.arraycopy(b, off, buffer, 0, len);
try {
serialPort.writeBytes(buffer);
} catch (SerialPortException e) {
throw new IOException(e);
}
}
}
需要实现SerialPortWrapper接口,进行接口参数配置
SerialPortWrapperImp.java
package com.docmgr.workstation.communication.protocol.modbus;
import com.serotonin.io.serial.SerialParameters;
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import jssc.SerialPort;
import jssc.SerialPortException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author Administrator
* @title: TestSerialPortWrapper
* @projectName workstation_yh
* @description: TODO
* @date 2021/06/04 000416:13
*/
public class SerialPortWrapperImp implements SerialPortWrapper {
private SerialPort port;
private String commPortId;
private int baudRate;
private int flowControlIn;
private int flowControlOut;
private int dataBits;
private int stopBits;
private int parity;
public SerialPortWrapperImp(String commPortId, int baudRate, int flowControlIn,
int flowControlOut, int dataBits, int stopBits, int parity){
this.commPortId = commPortId;
this.baudRate = baudRate;
this.flowControlIn = flowControlIn;
this.flowControlOut = flowControlOut;
this.dataBits = dataBits;
this.stopBits = stopBits;
this.parity = parity;
port = new SerialPort(this.commPortId);
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#close()
*/
@Override
public void close() throws Exception {
port.closePort();
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#open()
*/
@Override
public void open() throws Exception {
try {
port.openPort();
port.setParams(this.getBaudRate(), this.getDataBits(), this.getStopBits(), this.getParity());
port.setFlowControlMode(this.getFlowControlIn() | this.getFlowControlOut());
//listeners.forEach(PortConnectionListener::opened);
//LOG.debug("Serial port {} opened", port.getPortName());
} catch (SerialPortException ex) {
//LOG.error("Error opening port : {} for {} ", port.getPortName(), ex);
}
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getInputStream()
*/
@Override
public InputStream getInputStream() {
// TODO Auto-generated method stub
return new SerialInputStream(port);
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getOutputStream()
*/
@Override
public OutputStream getOutputStream() {
// TODO Auto-generated method stub
return new SerialOutputStream(port);
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getBaudRate()
*/
@Override
public int getBaudRate() {
// TODO Auto-generated method stub
return baudRate;
}
public int getFlowControlIn() {
return flowControlIn;
//return SerialPort.FLOWCONTROL_NONE;
}
public int getFlowControlOut() {
return flowControlOut;
//return SerialPort.FLOWCONTROL_NONE;
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getStopBits()
*/
@Override
public int getStopBits() {
// TODO Auto-generated method stub
return stopBits;
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getParity()
*/
@Override
public int getParity() {
// TODO Auto-generated method stub
return parity;
}
/* (non-Javadoc)
* @see com.serotonin.modbus4j.serial.SerialPortWrapper#getDataBits()
*/
@Override
public int getDataBits() {
// TODO Auto-generated method stub
return dataBits;
}
}
测试类
Test.java
modbusFactory.createAsciiMaster(wrapper);是采用了modbus的asc模式进行发送
modbusFactory.createRtuMaster(wrapper); 采用了modbus的rtu模式进行发送
package com.docmgr.workstation.communication.protocol.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.msg.*;
import java.util.Arrays;
/**
* @author Administrator
* @title: Test
* @projectName workstation_yh
* @description: TODO
* @date 2021/06/03 000316:45
*/
public class Test {
public static void main(String[] args) throws ModbusInitException {
String commPortId = "COM7";
int baudRate = 9600;
int flowControlIn = 0;
int flowControlOut = 0;
int dataBits = 7;
int stopBits = 1;
int parity = 0;
first(commPortId, baudRate, flowControlIn, flowControlOut, dataBits, stopBits, parity);
second(commPortId, baudRate, flowControlIn, flowControlOut, dataBits, stopBits, parity);
// SerialPortWrapperImp wrapper = new SerialPortWrapperImp(commPortId, baudRate, flowControlIn, flowControlOut, dataBits, stopBits, parity);
/*
//IpParameters ipParameters = new IpParameters();
//ipParameters.setHost("localhost");
ModbusFactory modbusFactory = new ModbusFactory();
ModbusMaster master = modbusFactory.createAsciiMaster(wrapper);
// ModbusMaster master = modbusFactory.createAsciiMaster(wrapper);
//ModbusMaster master = modbusFactory.createTcpMaster(ipParameters, false);
// ModbusMaster master = modbusFactory.createUdpMaster(ipParameters);
try {
master.init();
int slaveId = 1;
// readCoil(master, slaveId, 0, 10);
// readCoil(master, slaveId, 99, 200);
// readDiscreteInput(master, slaveId, 1, 10);
// readDiscreteInput(master, slaveId, 449, 72);
*//*
//This is Success
//读取保持寄存器
readHoldingRegisters(master, slaveId, 9, 125);
*//*
// readHoldingRegisters(master, slaveId, 9, 120);
// readInputRegisters(master, slaveId, 0, 1);
// readInputRegisters(master, slaveId, 14, 8);
// writeCoil(master, slaveId, 1, true);
// writeCoil(master, slaveId, 110, true);
*//*
//This is Success
//写单个寄存器
writeRegister(master, slaveId, 0, 1);
*//*
// writeRegister(master, slaveId, 14, 12345);
// readExceptionStatus(master, slaveId);
// reportSlaveId(master, slaveId);
// writeCoils(master, slaveId, 50, new boolean[] {true, false, false, true, false});
// writeCoils(master, slaveId, 115, new boolean[] {true, false, false, true, false});
//This is Success
//写多个寄存器
// writeRegisters(master, slaveId, 300, new short[] {1, 10, 100, 1000, 10000, (short)65535});
// writeRegisters(master, slaveId, 21, new short[] {1, 10, 100, 1000, 10000, (short)65535});
//This is Success
// writeMaskRegister(master, slaveId, 26, 0xf2, 0x25);
// readCoil(master, slaveId, 9, 5);
// readCoil(master, slaveId, 10, 5);
// readDiscreteInput(master, slaveId, 10, 6);
// readDiscreteInput(master, slaveId, 10, 5);
// readHoldingRegisters(master, slaveId, 9, 7);
// readHoldingRegisters(master, slaveId, 10, 5);
// readInputRegisters(master, slaveId, 0, 1);
// readInputRegisters(master, slaveId, 10, 5);
writeCoil(master, slaveId, 2088, true);
//writeCoil(master, slaveId, 2088, false);
// writeRegistert(master, slaveId, 4108, 10);
// writeRegister(master, slaveId, 14, 12345);
// readExceptionStatus(master, slaveId);
// reportSlaveId(master, slaveId);
// writeCoils(master, slaveId, 11, new boolean[] {false, true, false, false, true});
// writeCoils(master, slaveId, 10, new boolean[] {false, true, false, false, true});
// writeRegisters(master, slaveId, 11, new short[] {(short)65535, 1000, 100, 10, 1});
// writeRegisters(master, slaveId, 10, new short[] {(short)65535, 1000, 100, 10, 1});
// writeMaskRegister(master, slaveId, 9, 0xf2, 0x25);
// writeMaskRegister(master, slaveId, 10, 0xf2, 0x25);
// Automatic WriteMaskRegister failover test
// ModbusLocator locator = new ModbusLocator(slaveId, RegisterRange.HOLDING_REGISTER, 15, (byte)2);
// System.out.println(master.getValue(locator));
// master.setValue(locator, true);
// System.out.println(master.getValue(locator));
// master.setValue(locator, false);
// System.out.println(master.getValue(locator));
// BatchRead<String> batch = new BatchRead<String>();
// batch.addLocator("hr1", new ModbusLocator(31, RegisterRange.HOLDING_REGISTER, 80,
// DataType.TWO_BYTE_BCD));
// batch.addLocator("hr2", new ModbusLocator(31, RegisterRange.HOLDING_REGISTER, 81,
// DataType.FOUR_BYTE_BCD));
// BatchResults<String> results = master.send(batch);
// System.out.println(results.getValue("hr1"));
// System.out.println(results.getValue("hr2"));
// This's Successful Way to set Reg Data
// BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, 10, DataType.EIGHT_BYTE_INT_UNSIGNED);
// master.setValue(locator, 10000000);
// System.out.println(master.getValue(locator));
} finally {
master.destroy();
}*/
}
public static void first(String commPortId, int baudRate, int flowControlIn, int flowControlOut, int dataBits, int stopBits, int parity) {
SerialPortWrapperImp wrapper = new SerialPortWrapperImp(commPortId, baudRate, flowControlIn, flowControlOut, dataBits, stopBits, parity);
ModbusFactory modbusFactory = new ModbusFactory();
ModbusMaster master = modbusFactory.createAsciiMaster(wrapper);
try {
master.init();
int slaveId = 0;
writeCoil(master, slaveId, 2088, true);
} catch (ModbusInitException e) {
e.printStackTrace();
} finally {
master.destroy();
}
}
public static void second(String commPortId, int baudRate, int flowControlIn, int flowControlOut, int dataBits, int stopBits, int parity) {
SerialPortWrapperImp wrapper = new SerialPortWrapperImp(commPortId, baudRate, flowControlIn, flowControlOut, dataBits, stopBits, parity);
ModbusFactory modbusFactory = new ModbusFactory();
ModbusMaster master = modbusFactory.createAsciiMaster(wrapper);
try {
master.init();
int slaveId = 0;
writeCoil(master, slaveId, 2088, false);
} catch (ModbusInitException e) {
e.printStackTrace();
} finally {
master.destroy();
}
}
/**
* code 1
*
* @param master
* @param slaveId
* @param start
* @param len
*/
public static void readCoil(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadCoilsRequest request = new ReadCoilsRequest(slaveId, start, len);
ReadCoilsResponse response = (ReadCoilsResponse) 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();
}
}
/**
* code 2
*
* @param master
* @param slaveId
* @param start
* @param len
*/
public static void readDiscreteInput(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();
}
}
/**
* code 3
*
* @param master
* @param slaveId
* @param start
* @param len
*/
public static void readHoldingRegisters(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();
}
}
/**
* code 4
*
* @param master
* @param slaveId
* @param start
* @param len
*/
public static void readInputRegisters(ModbusMaster master, int slaveId, int start, int len) {
try {
ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, start, len);
ReadInputRegistersResponse response = (ReadInputRegistersResponse) 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();
}
}
/**
* code 5
*
* @param master
* @param slaveId
* @param offset
* @param value
*/
public static void writeCoil(ModbusMaster master, int slaveId, int offset, boolean value) {
System.err.println("进入接口-------");
try {
WriteCoilRequest request = new WriteCoilRequest(slaveId, offset, value);
WriteCoilResponse response = (WriteCoilResponse) master.send(request);
if (response.isException()) {
System.out.println("Exception response: message=" + response.getExceptionMessage());
} else {
System.out.println("Success");
}
} catch (ModbusTransportException e) {
e.printStackTrace();
} catch (Exception e) {
}
}
/**
* code 6
*
* @param master
* @param slaveId
* @param offset
* @param value
*/
public static void writeRegister(ModbusMaster master, int slaveId, int offset, int value) {
try {
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, 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();
}
}
/**
* code 7
*
* @param master
* @param slaveId
*/
public static void readExceptionStatus(ModbusMaster master, int slaveId) {
try {
ReadExceptionStatusRequest request = new ReadExceptionStatusRequest(slaveId);
ReadExceptionStatusResponse response = (ReadExceptionStatusResponse) master.send(request);
if (response.isException()) {
System.out.println("Exception response: message=" + response.getExceptionMessage());
} else {
System.out.println(response.getExceptionStatus());
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
/**
* code 17
*
* @param master
* @param slaveId
*/
public static void reportSlaveId(ModbusMaster master, int slaveId) {
try {
ReportSlaveIdRequest request = new ReportSlaveIdRequest(slaveId);
ReportSlaveIdResponse response = (ReportSlaveIdResponse) 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();
}
}
/**
* code 15
*
* @param master
* @param slaveId
* @param start
* @param values
*/
public static void writeCoils(ModbusMaster master, int slaveId, int start, boolean[] values) {
try {
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, start, values);
WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
if (response.isException()) {
System.out.println("Exception response: message=" + response.getExceptionMessage());
} else {
System.out.println("Success");
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
/**
* code 16
*
* @param master
* @param slaveId
* @param start
* @param values
*/
public static void writeRegisters(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();
}
}
/**
* code 22
*
* @param master
* @param slaveId
* @param offset
* @param and
* @param or
*/
public static void writeMaskRegister(ModbusMaster master, int slaveId, int offset, int and, int or) {
try {
WriteMaskRegisterRequest request = new WriteMaskRegisterRequest(slaveId, offset, and, or);
WriteMaskRegisterResponse response = (WriteMaskRegisterResponse) master.send(request);
if (response.isException()) {
System.out.println("Exception response: message=" + response.getExceptionMessage());
} else {
System.out.println("Success");
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
}
可以使用虚拟串口工具
配合SerialPro串口调试工具
或者串口监视工具AccessPort 进行对串口发送相关数据进行监视