一、Modbus背景介绍
Modbus是一种用于工业自动化控制系统的通讯协议,由Modcion(施耐德电气)于1979开发的,目的是为了实现不同设备之间的互操作性,广泛用于连接电子设备以实现数据交换。
开放标准:开放协议,任何人都可以免费试用和实现。
二、主要特点
Modbus适配多种物理层(RS232/RS485/以太网),仅定义协议数据单元(PDU、PTU),底层依赖物理层与数据链路层。
-
1、主从架构
采用主从架构。一个主设备可以与多个从设备通信,从设备之间不直接通信。主设备采用轮询/广播的方式发出命令,从设备响应。
-
- 主设备:主动发起请求(一般为PLC、HMI等),一条总线上仅有一个主站,地址0为广播地址。
-
- 从设备:被动响应(一般为传感器、变频器、IO等),地址1~247,仅响应匹配地址的请求。有的从设备可能会主动上传错误码。
-
2、多种传输方式
随着技术发展,Modbus也演变了多个版本和变体,以适应不同的通信需求和物理介质。比如常用的Modbus PTU、Modbus ASCII、Modbus TCP/IP等。
-
3、简洁的数据模型
定义了一种简单的数据模型,仅包含四种数据类型:离散输入、线圈、输入寄存器、保持寄存器。
三、Modbus通信流程
Modbus是一个请求/应答的协议,提供统一的功能码用于数据传输服务。
Modbus设计了一套简洁的通信格式,协议规定了PDU(protocol data unit)模型,即功能码+数据的格式。同时,为了适应多种传输模式,在PDU的基础上添加了必要的前缀(地址域)和后缀(差错校验)形成了ADU(application data uint)模型。

主站创建Modbus应用数据单元形成查询报文,其中功能码标识从机设备将要执行哪种操作。主机发送报文,从机设备接收报文,并根据功能码做出相应的动作,并将响应报文返回给主机设备。
一般来说,若从站收到的是正确报文,且接收无误的话,此时会返回正常响应报文。

但是有异常情况的话,从设备一般返回一个与原始功能码等同的码值,但是设置该原始功能码的最高有效位为逻辑1,从而通知主站。

四、常见的传输方式
Modbus可用于串行链路或TCP/IP以太网。传输方式定义了在传输过程中连续消息段的每一个字节,继而决定着如何将信息打包成消息域和如何解码等。
Modbus在OSI模型上:

4.1、Modbus PTU
PTU模式通过二进制格式传输数据,具有高效、可靠等特点,常用于串行链路上,比如RS232和RS485上。数据帧之间要有3.5个字符间隔。
帧结构:

4.2、Modbus ASCII
该模式以ASCII方式传输数据,在消息中每个8位的字节都将作为两个ASCII字符发送。消息以冒号(:即0x3A)开始,以回车换行符结束(0x0D),其它字段则采用十六进制为传输字符。具有文本可读,调试方便,适用于低速短距的场景。
Modbus设备通过不断侦测":"字符,当有一个冒号接收到时,便进入解码阶段,并开始解码下一个字段(地址域)来判断消息是否是发给自己的。消息帧中字符间的发送间隔时间最长不能超过1秒,否则接收设备将认为传输错误。
帧结构:

为什么我在开发主设备的时候,并不需要判断":"字符呢?一般是需要的,用于判别数据帧的开始。
4.3、Modbus TCP/IP
采用MBAP头(7字节)+RTU帧(无CRC),端口使用502,具有支持多主,跨网络等有点。(没用过,后续补充)
五、数据模型
Modbus中一个重要概念就是寄存器,所有的数据都存放在寄存器中,指一片内存区域。Modbus中寄存器是用于存储数据和状态信息的基本单元。
协议按照存放的数据类型和读写特性等,将寄存器分为四种,即线圈、离散输入状态、保持寄存器、输入寄存器。
| 寄存器种类 | 读写性 | 位宽 | 用途 |
|---|---|---|---|
| 线圈 | RW | 1bit | 输出端口,常用于继电器、阀门等 |
| 离散输入 | RO | 1bit | 输入端口,常用于采集开关量信号,如拨码开关等 |
| 保持寄存器 | RW | 16bit | 存储控制参数,常用于配置、控制参数等 |
| 输入寄存器 | RO | 16bit | 输入参数,常用于采集温度等模拟量信号 |
六、功能码
功能码用于告知从站操作类型,常见的功能码如下:
| 功能码 | 寄存器类型 |
|---|---|
| 1 | 读取线圈 |
| 2 | 读取离散输入 |
| 3 | 读取保存寄存器 |
| 4 | 读取输入寄存器 |
| 5 | 写入单个线圈 |
| 6 | 写入单个保存寄存器 |
| 15 | 写入多个线圈 |
| 16 | 写入多个保存寄存器 |
当从站识别出数据包,但确认请求中存在错误时,将返回异常代码恢复,而不是数据回复。异常代码一般由从站地址/单元号、设置了高位的功能代码副本和附加异常代码组成。比如功能代码为0x03,则异常功能代码副本为0x83。
附加异常代码常见的如下:
| 异常码 | 说明 | 备注 |
|---|---|---|
| 1 | 非法的功能码 | 查询中收到的功能代码不被从站识别或允许 |
| 2 | 非法的数据地址 | 寄存器不存在 |
| 3 | 非法的数据值 | 数据值对于从站来说是不可接受的 |
| 4 | 从设备故障 | 从站常识执行请求的操作时发生不可恢复的错误 |
| 5 | 从设备忙 | 从设备正在处理一个长时间的命令,主设备应稍后重试 |
七、如何使用Modbus
一般可以通过开源库或自行实现两种方式实现设备对Modbus协议的支持。
-
推荐 libmodbus(跨平台,支持 RTU/TCP)、FreeModbus(嵌入式,Slave 为主),快速部署。
-
自行实现步骤:串口初始化→帧接收→CRC/LRC 校验→功能码解析→数据读写→响应帧组装→发送。
-
可以访问 Modbus官方获取 Modbus 协议规范的副本。主要关注三个文件: (1) 应用层协议,定义功能代码和寻址; (2)串行线路(RTU)使用的定义; (3)以太网使用(TCP)的定义。