首页>>互联网>>物联网->一文搞懂物联网Modbus通讯协议

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

时间:2023-11-29 本站 点击:0

1 概述

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

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

免费无版税限制

容易部署

灵活限制少

2ModBus协议概述

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和以太网接口。

通讯示意图如下:

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

一次只有一个主机(Master)连接到网络

只有主设备(Master)可以启动通信并向从设备(Slave)发送请求

主设备(Master)可以使用其特定地址单独寻址每个从设备(Slave),也可以使用地址0(广播)同时寻址所有从设备(Slave)

从设备(Slave)只能向主设备(Master)发送回复

从设备(Slave)无法启动与主设备(Master)或其他从设备(Slave)的通信

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

单播模式

广播模式

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

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

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

Modbus Poll(Master)

Modbus Slave

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

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

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

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

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

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

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

3ModBus 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中无法正常下载,可以手动下载后放于项目中,并添加到项目库中。如下图所示:

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

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

ForaJDKinstallation:CopyRXTXcomm.jar---><JAVA_HOME>\jre\lib\extCopyrxtxSerial.dll---><JAVA_HOME>\jre\binCopyrxtxParallel.dll---><JAVA_HOME>\jre\bin

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

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

publicstaticSerialPortopen(StringportName,IntegerbaudRate,IntegerdataBits,IntegerstopBits,Integerparity){SerialPortresult=null;try{CommPortIdentifieridentifier=CommPortIdentifier.getPortIdentifier(portName);//打开端口CommPortcommPort=identifier.open(portName,2000);//判断是不是串口if(commPortinstanceofSerialPort){result=(SerialPort)commPort;//设置串口的参数result.setSerialPortParams(baudRate,dataBits,stopBits,parity);log.info("打开串口{}成功",portName);}else{log.info("{}不是串口",portName);}}catch(Exceptione){log.error("打开串口{}错误",portName,e);}returnresult;}

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

publicstaticvoidcreateRtuSlave(){//串口是COM3,波特率是9600SerialPortWrapperImplwrapper=newSerialPortWrapperImpl("COM3",9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE,0,0);ModbusFactorymodbusFactory=newModbusFactory();创建RTUSlavefinalModbusSlaveSetslave=modbusFactory.createRtuSlave(wrapper);//寄存器里可以设置线圈状态、离散输入状态、保持寄存器和输入寄存器//从站设备ID是1BasicProcessImageprocessImage=newBasicProcessImage(1);processImage.setInvalidAddressValue(Short.MIN_VALUE);slave.addProcessImage(processImage);//添加监听器,监听slave线圈状态和保持寄存器的写入processImage.addListener(newMyProcessImageListener());//设置数据setCoil(processImage);setInput(processImage);setHoldingRegister(processImage);setInputRegister(processImage);//开启线程启动newThread(()->{try{slave.start();}catch(ModbusInitExceptione){e.printStackTrace();}}).start();}

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

privatestaticvoidcreateRtuMaster()throwsException{//串口是COM4,波特率是9600SerialPortWrapperImplwrapper=newSerialPortWrapperImpl("COM4",9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE,0,0);ModbusFactorymodbusFactory=newModbusFactory();//RTUMasterModbusMastermaster=modbusFactory.createRtuMaster(wrapper);master.init();//从站设备ID是1intslaveId=1;//读取保持寄存器readHoldingRegisters(master,slaveId,0,3);//将地址为0的保持寄存器数据修改为0writeRegister(master,slaveId,0,0);//再读取保持寄存器readHoldingRegisters(master,slaveId,0,3);}

启动后输出如下所示:

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

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

来源:阿里云


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/IOT/1537.html