一文搞懂物联网Modbus通讯协议-阿里云开发者社区

开发者社区> JackWang1987> 正文

一文搞懂物联网Modbus通讯协议

简介: 一般来说,常见的物联网通讯协议众多,如蓝牙、Zigbee、WiFi、ModBus、PROFINET、EtherCAT、蜂窝等。而在众多的物联网通讯协议中,Modbus是当前非常流行的一种通讯协议。它一种串行通信协议,是Modicon公司于1979年为使用可编程逻辑控制器(PLC)通信而制定的,可以说,它已经成为工业领域通信协议的业界标准。
+关注继续查看

1 概述


       随着IT技术的快速发展,当前已经步入了智能化时代,其中的物联网技术将在未来占据越来越重要的地位。根据百度百科的定义,物联网(Internet of things,简称IOT )即“万物相连的互联网”,是互联网基础上的延伸和扩展的网络,物联网将各种信息有机的结合起来,实现任何时间、任何地点,人、机、物的互联互通。物联网从技术上来说,很重要的核心是通讯协议,即如何按约定的通讯协议,把机、物和人与互联网相连接,进行信息通信,以实现对人、机和物的智能化识别、定位、跟踪、监控和管理的一种网络。

       一般来说,常见的物联网通讯协议众多,如蓝牙、Zigbee、WiFi、ModBus、PROFINET、EtherCAT、蜂窝等。而在众多的物联网通讯协议中,Modbus是当前非常流行的一种通讯协议。它一种串行通信协议,是Modicon公司于1979年为使用可编程逻辑控制器(PLC)通信而制定的,可以说,它已经成为工业领域通信协议的业界标准。其优势如下:

  • 免费无版税限制
  • 容易部署
  • 灵活限制少

2 ModBus协议概述


       Modbus通讯协议使用请求-应答机制在主(Master)(客户端Client)和从(Slave)(服务器Server)之间交换信息。Client-Server原理是通信协议的模型,其中一个主设备控制多个从设备。这里需要注意的是:Modbus通讯协议当中的Master对应Client,而Slave对应Server。Modbus通讯协议的官网为www.modbus.org。目前官网组织已经建议将Master-Slave替换为Client-Server。从协议类型上可以分为:Modbus-RTU(ASCII)、Modbus-TCP和Modbus-Plus。本文主要介绍Modbus-RTU(ASCII)的通讯协议原理。标准的Modbus协议物理层接口有RS232、RS422、RS485以太网接口。

      通讯示意图如下:

1.jpg

   一般来说,Modbus通信协议原理具备如下的特征:

  • 一次只有一个主机(Master)连接到网络
  • 只有主设备(Master)可以启动通信并向从设备(Slave)发送请求
  • 主设备(Master)可以使用其特定地址单独寻址每个从设备(Slave),也可以使用地址0(广播)同时寻址所有从设备(Slave)
  • 从设备(Slave)只能向主设备(Master)发送回复
  • 从设备(Slave)无法启动与主设备(Master)或其他从设备(Slave)的通信

     Modbus协议可使用2种通信模式交换信息:

  • 单播模式
  • 广播模式

     不管是请求报文还是答复报文,数据结构如下:

2.jpg

    即报文(帧数据)由4部分构成:地址(Slave Number)+功能码(Function Codes)+数据(Data)+校验(Check) 。其中的地址代表从设备的ID地址,作为寻址的信息。功能码表示当前的请求执行具体什么操作,比如读还是写。数据代表需要通讯的业务数据,可以根据实际情况来确定。最后一个校验则是验证数据是否有误。其中的功能码说明如下:

3.jpg

  比如功能码为03代表读取当前寄存器内一个或多个二进制值,而06代表将二进制值写入单一寄存器。为了模拟Modbus通讯协议过程,这里可以借助模拟软件:

  • Modbus Poll(Master)
  • Modbus Slave

   具体的安装过程这里不再赘述。首先这里需要模拟一个物联网传感器设备,这里用Modbus Slave来定义,首先打开此软件,并定义一个ID为1的设备:

4.jpg

此功能码为03。另外,设置连接参数,示例界面如下:

5.jpg

下面再用Modbus Poll软件来模拟主机,来获取从设备的数据。首先定义一个读写报文。

6.jpg

然后再定义一个连接信息:

7.jpg

注意:两个COM口要使用不同的名称。

成功建立通讯后,通信的报文格式如下:

8.jpg

Tx代表请求报文,而Rx代表答复报文。

3 ModBus Java实现


       下面介绍一下如何用Java来实现一个Modbus TCP通信。这里Java框架采用Spring Boot,首先需要引入Modbus4j库。Maven依赖库的pom.xml定义如下:

 <dependency>
    <groupId>com.infiniteautomation</groupId>
    <artifactId>modbus4j</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>org.rxtx</groupId>
    <artifactId>rxtx</artifactId>
    <version>2.1.7</version>
</dependency>

其中的modbus4j库可能在Maven中无法正常下载,可以手动下载后放于项目中,并添加到项目库中。如下图所示:

15.jpg

注意:首次实用串口时,需要进行安装,否则会报 no rxtxSerial in java.library.path的错误。

访问http://fizzed.com/oss/rxtx-for-java 下载对应操作系统的库文件,解压后安装如下指导进行拷贝后安装。

For a JDK installation:
Copy RXTXcomm.jar ---> <JAVA_HOME>\jre\lib\ext
Copy rxtxSerial.dll ---> <JAVA_HOME>\jre\bin
Copy rxtxParallel.dll ---> <JAVA_HOME>\jre\bin

另外,需要注意,这里还需要串口支持,这里可以用虚拟串口软件来解决。

18.png

下面给出Java核心代码片段。

    public static SerialPort open(String portName, Integer baudRate, Integer dataBits,
                                  Integer stopBits, Integer parity) {
        SerialPort result = null;
        try {
           
            CommPortIdentifier identifier = CommPortIdentifier.getPortIdentifier(portName);
            // 打开端口
            CommPort commPort = identifier.open(portName, 2000);
            // 判断是不是串口
            if (commPort instanceof SerialPort) {
                result = (SerialPort) commPort;
                // 设置串口的参数
                result.setSerialPortParams(baudRate, dataBits, stopBits, parity);
                log.info("打开串口{}成功", portName);
            }else{
                log.info("{}不是串口", portName);
            }
        } catch (Exception e) {
            log.error("打开串口{}错误", portName, e);
        }
        return result;
    }

首先需要启动Modbus RTU Slave程序,核心代码片段如下:

    public static void createRtuSlave(){
        // 串口是COM3,波特率是9600
        SerialPortWrapperImpl wrapper = new SerialPortWrapperImpl("COM3", 9600,
                SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, 0, 0);
        ModbusFactory modbusFactory = new ModbusFactory();
        创建RTU Slave
        final ModbusSlaveSet slave = modbusFactory.createRtuSlave(wrapper);
        // 寄存器里可以设置线圈状态、离散输入状态、保持寄存器和输入寄存器
        //从站设备ID是1
        BasicProcessImage processImage = new BasicProcessImage(1);
        processImage.setInvalidAddressValue(Short.MIN_VALUE);
        slave.addProcessImage(processImage);

        // 添加监听器,监听slave线圈状态和保持寄存器的写入
        processImage.addListener(new MyProcessImageListener());
        //设置数据
        setCoil(processImage);
        setInput(processImage);
        setHoldingRegister(processImage);
        setInputRegister(processImage);

        // 开启线程启动
        new Thread(() -> {
            try {
                slave.start();
            }
            catch (ModbusInitException e) {
                e.printStackTrace();
            }
        }).start();
    }

而Modbus RTU Master程序,核心代码片段如下:

    private static void createRtuMaster() throws Exception{
        //串口是COM4,波特率是9600
        SerialPortWrapperImpl wrapper = new SerialPortWrapperImpl("COM4", 9600,
                SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, 0, 0);
        ModbusFactory modbusFactory = new ModbusFactory();
        //RTU Master
        ModbusMaster master = modbusFactory.createRtuMaster(wrapper);
        master.init();
        // 从站设备ID是1
        int slaveId = 1;
        // 读取保持寄存器
        readHoldingRegisters(master, slaveId, 0, 3);
        // 将地址为0的保持寄存器数据修改为0
        writeRegister(master, slaveId, 0, 0);
        // 再读取保持寄存器
        readHoldingRegisters(master, slaveId, 0, 3);
    }

启动后输出如下所示:

//Slave
[Thread-1] INFO cn.wu.demo.modbus4j.util.SerialPortUtils - 打开串口COM3成功
保持寄存器地址=0,旧值=8,新值=0
//Master  //////////////////////////////////////////////////////////////////////  
[main] INFO cn.wu.demo.modbus4j.util.SerialPortUtils - 打开串口COM4成功
读取保持寄存器=[8, 56, 0]
写保持寄存器成功
读取保持寄存器=[0, 56, 0]

参考开源项目:https://github.com/wu-boy/modbus4j

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【物联网云端对接-4】通过MQTT协议与百度云进行云端通信
百度云的天工物联网服务目前包括:物接入、物解析、物管理、时序数据库和规则引擎等5大部分,本篇文章仅介绍物接入。
1385 0
【STM32 .Net MF开发板学习-05】PC通过Modbus协议远程操控开发板
从2002年就开始接触Modbus协议,以后陆续在PLC、DOS、Windows、.Net Micro Framework等系统中使用了该协议,在我以前写的一篇博文中详细记载了这一段经历,有兴趣的朋友可以看一看《我的Modbus Slave/Client开发历程(Rtu/AscII/Tcp)》。
582 0
嵌入式系统之Modbus TCP to Modbus Rtu协议转换器开发
嵌入式系统之Modbus TCP to Modbus Rtu协议转换器开发
591 0
如何从零设计一种物联网组网协议
物联网的基础是将万物连接起来,他是如何连接起来的,就是通过物联网的通信和组网协议。本文将从物联网通信协议现状分析入手,讲述如何从零设计一种物联网组网协议。
59 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4504 0
HTTP协议接入物联网平台(Getman模拟)
物联网平台通过HTTP连接通信(Getman模拟)
2278 0
+关注
JackWang1987
硕士,毕业于中国矿业大学,徐州软件协会副理事长,从业十余年,发表论文数十篇,著书四本。
64
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载