物联网---03.Modbus协议实现与设备的通讯,收发信息,实现对设备信息的采集
一、扫盲:什么是modbus?
Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于工业现场的总线协议
Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一种通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一个控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。
modbus本身就是一个通信协议,可以基于串口,也可以基于网口,基于串口的有RTU;基于网口的有TCP,默认端口号为502,通常我们把服务器端作为主站,将带有modbus模块的设备作为从站处理。利用modbus从寄存器中读取或写入数据
modbus功能码参照表:
二、请求报文案例
主站向从站发送请求报文:01 03 00 01 00 02 95 CB
01代表设备地址
03代表功能码(读取保存寄存器的值)
00 01代表采集点对应的寄存器号
00 02代表读取两个连续寄存器的值
95 CB代表01 03 00 01 00 02计算多得的CRC校验值
从站向主站放回的数据报文:01 03 04 00 00 00 00 FA 33
01代表设备地址
03代表功能码(读取保存寄存器的值)
04代表设备返回的数据个数(单位为字节)
00 00 00 00代表为数据返回的连续两个寄电器的数据
FA 33代表01 03 04 00 00 00 00计算所得的CRC校验码
最后向大家推荐一款modbus从站虚拟机,可以用做测试【ModbusSlave.exe】
从站虚拟机测试案例:
提供一个读取及写入的工具类:
依赖jar包:commons-codec-1.6.jar modbus4J.jar seroUtils.jar
<!-- https://mvnrepository.com/artifact/org.apache.directory.studio/org.apache.commons.codec -->
<dependency>
<groupId>org.apache.directory.studio</groupId>
<artifactId>org.apache.commons.codec</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.0.3</version>
</dependency>
<!-- 需要下载 -->
<dependency>
<groupId>com.automation</groupId>
<artifactId>seroUtils</artifactId>
<systemPath>${project.basedir}/src/lib/seroUtils.jar</systemPath>
<scope>system</scope>
</dependency>
seroUtils.jar 下载
链接:https://pan.baidu.com/s/1sbjR9w4JWe5ctBcLZwb8UA
提取码:c9sv
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.ModbusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;
import com.serotonin.util.queue.ByteQueue;
public class ReadAWriteUtil {
/**
* 批量写数据到保持寄存器
* @param ip 从站IP
* @param port modbus端口
* @param slaveId 从站ID
* @param start 起始地址偏移量
* @param values 待写数据
*/
public static void modbusWTCP(String ip, int port, int slaveId, int start, short[] values) {
ModbusFactory modbusFactory = new ModbusFactory();
// 设备ModbusTCP的Ip与端口,如果不设定端口则默认为502
IpParameters params = new IpParameters();
params.setHost(ip);
// 设置端口,默认502
if (502 != port) {
params.setPort(port);
}
ModbusMaster tcpMaster = null;
// 参数1:IP和端口信息 参数2:保持连接激活
tcpMaster = modbusFactory.createTcpMaster(params, true);
try {
tcpMaster.init();
System.out.println("=======初始化成功========");
} catch (ModbusInitException e) {
System.out.println("初始化异常");
}
try {
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request);
if (response.isException()){
System.out.println("Exception response: message=" + response.getExceptionMessage());
}else{
System.out.println("Success");
}
} catch (ModbusTransportException e) {
e.printStackTrace();
}
}
/**
* 读保持寄存器上的内容
* @param ip 从站IP
* @param port modbus端口
* @param start 起始地址偏移量
* @param readLenth 待读寄存器个数
* @return
*/
public static ByteQueue modbusTCP(String ip, int port, int start,int readLenth) {
ModbusFactory modbusFactory = new ModbusFactory();
// 设备ModbusTCP的Ip与端口,如果不设定端口则默认为502
IpParameters params = new IpParameters();
params.setHost(ip);
//设置端口,默认502
if(502!=port){
params.setPort(port);
}
ModbusMaster tcpMaster = null;
tcpMaster = modbusFactory.createTcpMaster(params, true);
try {
tcpMaster.init();
System.out.println("========初始化成功=======");
} catch (ModbusInitException e) {
return null;
}
ModbusRequest modbusRequest=null;
try {
//功能码03 读取保持寄存器的值
modbusRequest = new ReadHoldingRegistersRequest(1, start, readLenth);
} catch (ModbusTransportException e) {
e.printStackTrace();
}
ModbusResponse modbusResponse=null;
try {
modbusResponse = tcpMaster.send(modbusRequest);
} catch (ModbusTransportException e) {
e.printStackTrace();
}
ByteQueue byteQueue= new ByteQueue(1024);
modbusResponse.write(byteQueue);
System.out.println("功能码:"+modbusRequest.getFunctionCode());
System.out.println("从站地址:"+modbusRequest.getSlaveId());
System.out.println("收到的响应信息大小:"+byteQueue.size());
System.out.println("收到的响应信息值:"+byteQueue);
return byteQueue;
}
}

浙公网安备 33010602011771号