MODBUS是一种应用层消息协议。自1979年以来,一直属于工业自动化的一项标准协议。
背景
研究MODBUS是源于之前对MQTT的研究,所以产生了对[工业]物联网协议的兴趣。
事实上,MODBUS是一个标准的工业自动化设备通信协议,协议规范中所用到的术语还是和工业设备有关联的。
因此,对待MODBUS协议(即:用代码实现它),建议从工业控制程序入门(PLC),从而更精准的理解其规范的含义。如果仅仅做的是[工业]物联网协议转换的后台服务,可以不用深入了解,因为MODBUS数据结构就是两部分组成:1.功能码 (Function codes) 2. 数据 (Data)
1. 官方信息
1.1 协议规范列表
1.2 协议规范说明
版本: V1.1b3
目标:描述MODBUS协议框内的“功能码”使用规范
版本: V1_0b
目标:描述MODBUS协议消息基于TCP/IP传输方法
版本:V1_02
目标:描述串行线路上的MODBUS协议
2. 前置基础知识
收获关键词:离散(Discretes),线圈(Coils),寄存器(Register)
在MODBUS的数据模型描述中,会用到这些关键词,如果之前一直是在做纯软件开发,可能会感觉到难以理解。
2.1 PLC
开始学习MODBUS之前,有一个概念需要介绍一下:PLC
可编程逻辑控制器(Programmable Logic Controller,PLC),一种具有微处理器的数字电子设备,用于自动化控制的数字逻辑控制器,可以将控制指令随时加载存储器内存储与运行。
PLC出现于1964年,源于增效节本,替换之前“硬接线”方式的继电器。
比如:通过PLC控制电灯
关于PLC的详细内容,可自行搜索,这里仅仅是为了在学习MODBUS之前,了解一点PLC相关的内容,有助于理解MODBUS中提到的一些概念名词
如果对PLC编程有兴趣,推荐几个链接
-
PLC组成
2.2 PLC梯形图编程
注意
PLC编程语言有5种,这里介绍的是梯形图编程。
梯形图(LD)、指令表(IL)、功能模块图(FBD)、顺序功能流程图(SFC)及结构化文本(ST)
梯形图是一种PLC编程语言,也被称为梯形逻辑(Ladder Logic)。之所以称为梯形图,是因为 这种程序由一条条水平线构成,看起来很像梯子
注意 梯形图编程的工具是PLC设计商提供的。
- 1 : 横线 / 梯级
- -||- : 触点(输入)
- -()- : 线圈(输出)
触点(contacts)和线圈(coils)是离散编程元件,处理布尔变量状态。
“触点”和“线圈”依然沿用了继电器种的概念
在PLC中,“触点” 和 “线圈” 操作的其实是PLC 寄存器
PLC程序运行模拟图,共分为三个阶段:1. 扫描输入 2. 运行 3. 输出
PLC控制电灯实例
开关按下,发送信号给PLC, PLC输出信号控制灯泡
与PLC连接的设备分为两类:1. 输入设备 2.输出设备
-
输入设备为PLC提供信号或者数据
-
输出设备等待PLC提供信号或者数据
所有的输入&输出设备有两种基本类型:1. 离散(数字) 2.模拟
离散设备是指只有开和关两种状态的输入和输出, 模拟设备是指有无数种状态的输入和输出
PLC 中的
线圈(coil)类似于电气世界中的单个离散继电器(即继电器线圈),读取时返回单个开或关(0 或 1)值或状态。PLC 中的线圈可以是内部线圈,也可以是离散输出。内部线圈(也称为逻辑线圈、虚线圈等)是 PLC 梯形逻辑程序中使用的软件线圈,与外界没有直接联系。离散输出线圈是 PLC 梯形逻辑程序线圈,通过软件连接到 PLC I/O 中的物理离散输出点。在 Modicon PLC 中,线圈寻址为 0xxxx,"x "的数量是 Modicon 处理器的功能。
保持寄存器(holding register)通常类似于数值。在 Modicon 术语中(我认为这是 "保持寄存器 "一词的来源),保持寄存器是一个 16 位字,通常包含 15 位有符号整数(+/-32767),有时也包含 16 位数。在较早的 Modicon PLC(如 484)中,保持寄存器最高只能到 999,而一些 Modicon 584 和早期的 984 最高只能到 9999。在 Modicon PLC 中,保持寄存器的地址为 4xxxx,"x "的数量是 Modicon 处理器的功能。保持寄存器通常包含整数,如定时器预置、定时器累计值、计数器预置、计数器累计值、数学运算结果、模拟值等。有些系统将多个连续的保持寄存器组合在一起
3. MODBUS
- PDU:协议数据单元
- ADU:应用数据单元
3.1 数据格式
协议核心数据结构:
- 功能码
- 数据
协议通用数据结构, 规范“V1_1b3”
- 地址
- 功能码
- 数据
- 错误检查
基于串口通信的MODBUS数据格式, 规范“V1_02”
示意图中的 MODBUS SERIAL LINE PDU 指的就是协议通用数据结构的ADU(即应用数据)
基于TCP/IP通信的MODBUS数据格式, 规范“V1_0b”
3.2 通信架构
MODBUS 基于三种方式实现通信:
- 互联网 - TCP/IP
- 异步串口 - 采用 “主从模式”,介质分为 a.有线:RS232,RS485;b.光纤 c.无线
- 高级链路控制
MODBUS协议可以在所有的网络架构中轻松实现通信
3.3 数据结构定义
ADU 在串口线上的每帧最大传输数据承载量256个字节 PDU 在串口线上的每帧最大传输数据承载量=256 - 1(地址) - 2(校验码) = 253 个字节
PDU是MODBUS的协议数据,在任何通信方式下,其都应该有固定的尺寸规则,因此PDU最大尺寸永远是253个字节
基于TCP的 MODBUS ADU尺寸 = 253 + 7(MBAP) = 260 个字节
3.3.1 基于串口通信
在串口通信中,MODBUS的数据传输有两种类型,MODBUS_RTU 和 MODBUS_ASCII
数据传输采用“大端模式”
3.3.1.1 RTU类型帧
占用字节的示意图
3.3.1.2 ASCII类型帧
占用字节的示意图
消息(message)编码规则:每8bit的字节会被拆分为两个字符的字节
例如:0x98, 根据ASCII表得知0x98中的9对应的16进制为0x39, 同理,0x98中的8对应的16进制为0x38
从上例可知,一个16进制表示字节,会被分拆为两个字符(如 '9' , '8'), 然后再将‘9’ & ‘8’转换为16进制
3.3.2 基于TCP/IP通信
MODBUS消息基于TCP/IP通信时,默认端口为502
数据传输采用“大端模式”
3.4 功能码(Function/Function code)
通过上边内容的了解,不管是基于TCP/IP还是串口来实现MODBUS,都会包含一个PDU-协议数据单元(功能码+数据 [即,Function Code + Data] )
在MODBUS协议中已明确定义了19个功能码,其作用详情见规范“V1_1b3”
- 0x01 -读取 线圈(Read Coils)
- 0x02 -读取 离散输入(Read Discrete Inputs)
- 0x03 -读取 保持寄存器(Read Holding Registers)
- 0x04 -读取 输入寄存器 (Read Input Registers)
- 0x05 -写入 单个线圈(Write Single Coil)
- 0x06 -写入 单个寄存器(Write Single Register)
- 0x07 -读取 异常状态(Read Exception Status)
- 0x08 -诊断
- 0x0b -读取 通信事件计数器
- 0x0c -读取 通信事件日志
- 0x0f -写入 多个线圈
- 0x10 -写入 多个寄存器
- 0x11 -上报多个服务器ID
- 0x14 -读取 文件记录
- 0x15 -写入 文件记录
- 0x16 -屏蔽写寄存器
- 0x17 -读取/写入 多个寄存器
- 0x18 -读取FIFO队列
- 0x2B -封装接口传输
如果对这些功能码感觉有点难以理解,可以先不用深究,从协议规范角度来讲,它就是一个常量值,属于PDU(协议数据单元)的一部分。
功能码其实不止这19种,因为协议规范中,已明确定义了功能码的分类和值范围
- 类型:1.公共功能码(PUBLIC function codes) 2.用户功能码(User Defined Function codes) 3.预留功能码
- 值范围
功能码范围:1~255,128 - 255用于预留码和异常码(规范“V1_1b3”)
The function code field of a MODBUS data unit is coded in one byte. Valid codes are in the range of 1 ... 255 decimal (the range 128 – 255 is reserved and used for exception responses).
注意规范“V1_1b3”中的"Annex A (Informative)"部分,提到有一些功能码/子功能码不属于协议规范,这些码被保留下来,用于特殊用途。8/19; 8/21-65535, 9, 10, 13, 14, 41, 42, 43/0-12, 43/15-255,90, 91, 125, 126, 127
4.1 子功能码
协议中还定义了“子功能码”,仅出现在串口通信网络中,作用:为功能码提供更多操作。在PDU结构(功能码+数据)中,位于“数据”部分
子功能码占用2个字节,值范围是0 - 65535(即十六进制 0x0000 - 0xffff)
和功能码一样,MODBUS协议已明确定义了15个子功能码
规范 “V1_1b3”-6.8.1章节
3.5 数据模型
MODBUS的数据模型是基于不同类型的四张表构建的。
Slave设备的信息存储在四个不同的表中。两个表存储 "开/关" 离散值(线圈),两个表存储数子值(寄存器)。线圈和寄存器各有一个只读表和读写表。
数据模型
| Primary tables | Object type | Type of | Comments |
|---|---|---|---|
| Discretes Input(离散输入) | Single bit | Read-Only | This type of data can be provided by an I/O system. |
| Coils(线圈) | Single bit | Read-Write | This type of data can be alterable by an application program. |
| Input Registers(输入寄存器) | 16-bit word | Read-Only | This type of data can be provided by an I/O system |
| Holding Registers(保持寄存器) | 16-bit word | Read-Write | This type of data can be alterable by an application program. |
MODBUS是工业通信协议,因此在这个数据模型中的表格命名,其实非常切合工业控制场景中的说法。这就是为什么在前边需要了解一下PLC相关内容。
但是这个数据模型在英文模式下,感觉还是很难理解,下边是“恩艾 (中国) 仪器有限公司”的总结
“恩艾 (中国) 仪器有限公司” 将Primary tables意译为“内存区块”,这个叫法和规范中所提供示意图更加能对的上,并且也符合实操看到现象。
3.6 地址模型
MODBUS 应用协议精确定义了PDU地址规则。
- 在MODBUS PDU中,每个数据的地址范围为0至65535
- 数据模型是由4个类型块组成,每个类型块由若干个从1到n编号的元素组成
MODBUS数据模型必须与设备应用程序绑定, MODBUS数据模型与设备应用程序之间的映射完全取决于供应商的设备.
为了更好的理解供应商对数据模型和设备应用程序的作用,这里以 西门子S7-300 来做一说明
3.6.1 西门子 S7-300
文档 “GOULD-MODBUS 协议概述” 中详细对S7-300的数据模型和地址模型做了说明
从“地址表示”中,可以十分清楚的看到“数据类型”对应的地址
3.7 功能码使用
读取Slave modbus的线圈状态,分别从规范,西门子s7-300,模拟软件,modbustools.com 四个来源展示一下 0x01 功能码的用法
3.7.1 根据 规范“V1_1b3”
读取20-38编号的线圈状态
线圈的默认地址从0开始,对应的编号为1
因此,编号20对应起始地址0x0013, 编号38对应的终止地址为0x0026 = 0x0013(起始地址)+0x0013(线圈数量)
同理返回值27-20,代表 0x001b地址-0x0013地址, 总共8位,其值为0xCD, 二进制 1100 1101
3.7.2 根据 西门子S7-300
章节“6.1 功能代码01”
由于S7-300支持的是RTU帧类型传输,所以“请求”命令中有“从站地址”。
3.7.3 根据 模拟软件
www.simplymodbus.ca/RTUmaster.h…
在示意图中,找到“SEND”按钮,按钮左边便是功能码命令.
如图所示
- Master选择的是RTU模式
- Slave地址:0x0A
- 功能码:0x03
- 起始地址:0x0000
- 数量:0x0014
- 校验码:0x44be
3.7.4 根据 modbustools.com样例
样例来源:www.modbustools.com/modbus.html…
读取13个线圈,线圈编号为11-23,起始地址4
3.8 进阶
通过了解MODBUS协议的PDU,数据模型之后,如果还有兴趣继续进一步研究。可以根据你的方向从两个文档入手
- 基于串口通信的modbus modbus.org/docs/Modbus…
- 基于TCP/IP的modbus modbus.org/docs/Modbus…
3.8 MODBUS 开源代码
Java版本: jamod.sourceforge.net/
C版本:libmodbus.org/
4 总结
- MODBUS协议数据结构是非常简单的
- 大多数公司不用从0实现MODBUS协议
- 了解MODBUS协议,会阅读MODBUS规范,熟练掌握MODBUS设备供应商手册
入行关键词
- MODBUS 设备组网
- MODBUS RS232 RS485
- MODBUS 传感器
- MODBUS PLC
- RJ45 RS232 RS485
- PLC Coils Register
祝好运!