java中使用modbusTcp与plc通信
Posted FreeFly辉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中使用modbusTcp与plc通信相关的知识,希望对你有一定的参考价值。
本人只是用此协议写过上位机,所以这里介绍的只是在java中的一些使用
首先引入jar包
<dependency>
<groupId>com.intelligt.modbus</groupId>
<artifactId>jlibmodbus</artifactId>
<version>1.2.9.7</version>
</dependency>
下面是自己封装的统一连接类
@Data
@Slf4j
public class ModBusConnector
private static final Map<InetAddress, ModBusConnector> connectorMap = new HashMap<>();
private static final int MOD_BUS_PORT = 502;
private static final int SERVER_ADDRESS = 1;
private static final boolean KEEP_ALIVE = true;
private final ModbusMaster modbusMaster;
private final InetAddress ip;
protected ModBusConnector(ModbusMaster modbusMaster,InetAddress ip)
this.modbusMaster = modbusMaster;
this.ip = ip;
public static ModBusConnector fetchOrCreate(InetAddress ip, int timeout)
ModBusConnector connector = connectorMap.get(ip);
if (connector == null)
ModbusMaster masterTCP = ModbusMasterFactory.createModbusMasterTCP(new TcpParameters(ip, MOD_BUS_PORT, KEEP_ALIVE));
connector = new ModBusConnector(masterTCP, ip);
log.info("ModBus connector connecting: ", connector);
connector.getModbusMaster().setResponseTimeout(timeout);
try
connector.getModbusMaster().connect();
log.info("ModBus connector connected: ", connector);
catch (ModbusIOException e)
throw new IllegalStateException(e+ip.getHostAddress());
return connector;
public static ModBusConnector fetchOrCreate(InetAddress ip)
return fetchOrCreate(ip, 3000);
public ReadHoldingRegistersResponse readRegisters(PlcReadRequest readRequest)
return WrappingUtil.runWithRetry(() ->
final long sending = System.currentTimeMillis();
// log.debug("sending modbus read request: " +
// "waiting consume ms, ip=, request=", (sending - wait), ip, readRequest);
ModbusRequest request;
synchronized (modbusMaster)
try
if (!modbusMaster.isConnected())
modbusMaster.connect();
request = ModbusRequestBuilder.getInstance().buildReadHoldingRegisters(SERVER_ADDRESS,readRequest.getStartAddress(),readRequest.getQuantity());
final ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) modbusMaster.processRequest(request);
if (response.isException())
throw new IllegalStateException("ModBus返回异常:" + response.getModbusExceptionCode());
final long sent = System.currentTimeMillis();
log.debug("Successfully sent modbus read request : " +
"sending consume ms, ip=, request=, response: "
,(sent - sending),ip,readRequest,response.getHoldingRegisters().getRegisters());
return response;
catch (Exception e)
if (isConnected())
disconnect();
throw new IllegalStateException(e);
, PlcConfig.getRetryTimes(),new IllegalStateException("failed refresh rgv status"+ip.getHostAddress()));
public void writeRegisters(PlcWriteRequest writeRequest)
WrappingUtil.runWithRetry (() ->
final long wait = System.currentTimeMillis ();
final long sending = System.currentTimeMillis ();
log.debug ("sending modbus write request: " +
"waiting consume ms, ip=, request=", (sending - wait), ip, writeRequest);
ModbusRequest request;
synchronized (modbusMaster)
try
if (!modbusMaster.isConnected())
modbusMaster.connect();
request = ModbusRequestBuilder.getInstance().buildWriteMultipleRegisters(SERVER_ADDRESS,writeRequest.getStartAddress(),writeRequest.getRegisters());
ModbusResponse response = modbusMaster.processRequest(request);
final long sent = System.currentTimeMillis();
log.info("successfully sent modbus write request : time=" +
"sending consume ms, ip=, request=, response: ",System.currentTimeMillis(),(sent - sending),ip,writeRequest,response.getModbusExceptionCode());
catch (Exception e)
if (isConnected())
disconnect();
throw new IllegalStateException(e);
, PlcConfig.getRetryTimes (),new IllegalStateException("failed send command rgv status"+ip.getHostAddress()));
public boolean isConnected()
return modbusMaster.isConnected();
public void disconnect()
if (modbusMaster != null)
if (!modbusMaster.isConnected())
log.info("connection already disconnected ",this);
else
try
modbusMaster.disconnect();
catch (ModbusIOException e)
log.info("modbus disconnected false: ",this,e);
throw new IllegalStateException(e);
log.info("modbus disconnected success: ",this);
代码快中用到了自己封装的工具类会放在文章结尾,这里截图解释以下关键部分
建立连接
读请求
写请求
关键理解
java中每个 int 是 4个字节 32位,但是寄存器中int数据类型是 16 位,而一个int类型就是寄存器中的一个地址位。好比我想在 寄存器的第2个地址位的倒数第2个bit位写入 1,那么java中构建的就是
int [2] = new int[2]
int[1] = 1<<2//第几个bit位就要向前移几位
注意,此时随在第二个地址位写了 数值 2,但是由于java中int默认值是0,所以这样构建还会把第一个地址位数据置0,所以如果不想影响到第一个地址为数值,需要如下构建
int [1] = new int[1]
int[0] = 1<<2//第几个bit位就要向前移几位
此时下发时起始地址为要携程 1,不能再是 0
还有一点要注意的,一个plc中一个int如果只用了 8 个bit位,那么这 8个bit位是 16位中的高8位,即先高8位后低8位。
以上是关于java中使用modbusTcp与plc通信的主要内容,如果未能解决你的问题,请参考以下文章
西门子300PLC连接组态王KingSCADA实现ModbusTCP通信
三菱Q系列PLC与上位机易控组态软件ModbusTCP通信案例