物联网---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

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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><br>     <groupId>com.automation</groupId><br>     <artifactId>seroUtils</artifactId><br>     <systemPath>${project.basedir}/src/lib/seroUtils.jar</systemPath><br>     <scope>system</scope><br>   </dependency>

  

seroUtils.jar 下载

链接:https://pan.baidu.com/s/1sbjR9w4JWe5ctBcLZwb8UA
提取码:c9sv

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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; 
    }
}

  

posted @   打工仔-也想飞  阅读(817)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
点击右上角即可分享
微信分享提示