目录
ModBus概述
Modbus 是一种串行通讯协议,是 Modicon 公司(已被施耐德电气 Schneider Electric 收购)于 1979 年为使用可编程逻辑控制器(PLC)通信而发表。Modbus 已经成为工业领域通信协议事实上的业界标准,并且现在是工业电子设备之间常用的连接方式。Modbus 比其他通信协议使用的更广泛的主要原因有:
- 公开发表并且无著作权要求
- 易于部署和维护
- 对供应商来说,修改移动本地的比特或字节没有很多限制
ModBus协议常见类型
Modbus 协议当前存在用于串口、以太网以及其他支持互联网协议的网络的版本。
大多数 Modbus 设备通信通过串口 EIA-485、RS232 物理层进行。
对于串行连接,存在两个变种,他们分别是 ModBus ASCII 和 ModBus RTU 。它们在数值数据表示和协议细节上略有不同。Modbus RTU 是一种紧凑的,采用二进制表示数据的方式,Modbus ASCII 是一种人类可读的,冗长的表示方式。这两个变种都使用串行通信(serial communication)方式。
RTU 格式后续的命令/数据带有 CRC 的校验和,而 ASCII 格式采用 纵向冗余校验 的校验和。
此外,ASCII 格式有 特殊的帧头 :(ASCII 码 3AH)和 结束标志 回车换行符(ASCII 码 0DH,0AH)
对于通过 TCP/IP 的连接,存在多个 Modbus/TCP 变种,由于 TCP 是可靠的(三次握手四次挥手,维持在线,重传机制),因此这种方式不需要再增加 校验和 计算。
Modbus TCP帧格式可查看:modbus tcp 数据报文结构
ModBud RTU
工作方式
Modbus 是一个主/从协议,该协议规定,通讯设备分为主设备和从设备。
Modbus RTU 中有一个主设备,最多可以有 247 个从设备。 每个从设备由从地址 1 到 247 标识。
主机
主机可连接多个从机,在 ModBus RTU 协议中,从机地址有 8bit,其中 0x00 作为广播地址,0x01 ~ 0xF7(1 ~ 247)作为从机地址,剩余 8 个地址为协议保留。回到正题,主机可以从从机获取信息(读寄存器),亦可以写入信息到从机(写寄存器)。
自动化生产系统中的中央控制器就是典型的 Modbus主机。
从机
Modbus RTU 从机 是响应主机请求的设备。 从机接收到主机请求,一般的处理方式有两种:积极响应(分析请求并执行相应的动作),异常响应(CRC校验出错等)。
注意:
上文提及的寄存器并非真的寄存器,而是一个抽象的概念,表征某类数据,例如:温度,湿度
所以通讯必须由主设备发起,没有办法要求从设备 “报告异常”(构建在以太网的 TCP/IP 协议之上,被称为 open-mbus 除外)主设备必须循环的询问每个从设备,并查找数据中的变化。在带宽可能比较宝贵的应用中,这种方式在应用中消耗带宽和网络时间,例如在低速率的无线链路上。
若将 ModBus 应用与无线传输上,则需额外考虑以下问题
- 由于我们将 ModBus 协议帧通过无线传输,那么我们的 ModBus 协议帧需要满足无线通讯的协议。以 BLE 为例,BLE数据是通过特征值发送出去的,每个特征值有 20byte ,故而当 ModBus 协议总长度 大于20byte 时,我们需要采取数据分包的策略,即将 一个 ModBus协议帧 拆分成 多个 Modbus协议帧 发送。否则从机收到的数据是断帧的,这就需要从机将断帧重新组合成 完整的 ModBus协议帧 ,而这是 易错且低效 的(更长的数据增加了出错的风险,且重发需重发所有帧)。
ps:因而常规的做法还是将 ModBus协议 所携带的数据进行分包,形成多个ModBus协议包送入无线发送。
同一个 Modbus RTU 网络中不允许出现两台设备地址相同,这样会导致无线信号出现干扰,不能成功接收数据。
断帧方式
由于 ModBus 协议没有限制数据长度。在 ModBus RTU模式中规定,消息发送至少需要以 传输3.5个帧长度所需要的时间 作为停顿间隔开始。在最后一位数据传输完成后,至少需要 传输3.5个帧长度的时间 作为停顿标定消息的结束。
断帧时长的计算
首先我们先了解的概念
波特率:每秒通过信道传输的信息量称为位传输速率,也就是每秒钟传送的二进制位数,波特率 9600 即 9600 bit/s
在 UART 中,若规定设置起始位1bi t,数据位 8bit,无校验位(若有,奇偶校验也占1bit)结束标志1bit
则一个 UART帧 共计 10bit
在波特率为 9600 的情况下,每秒钟可发送 (9600bit/s)/10bit = 960帧
那么发送一个帧所需要的时间为 1/960 ≈ 1.04ms
按照前面的规定,断帧时间至少需要1.04*3.5 = 3.645ms
ps:注意不要和下文的超时时长搞混了
完整通讯流程图
注意:
- 从机对于广播帧是不发送应答的
- 超时处理
图中亦描述了一个现象,即主机发送请求,但发送出错导致从机无应答。
按照之前的协议的设定,主机应该在苦苦等待从机应答...若无应答岂不是主机一直阻塞或通讯阻塞?
作为一个成熟的协议,当然也考虑到了这些问题
采用的方法也很简单,即 超时处理机制。主机超出设定时间未接收到应答包,则会超时重发。
超时时间需要自行计算,计算方法见 西门子中国-Modbus 通讯注意事项及测试(续)
帧格式
正常帧
Addr(从机地址)
8bit | CMD(功能码)
8bit | Reg(寄存器地址)
16bit
| Num(数据长度)
16bit
| Data(数据)
不定长(8bit * n) n >= 0 | CRC(校验位)
16bit |
可能有人会说,这和上图 ModBus协议常见类型 展示的图片不一样啊,其实还是一样的,只是将数据1和数据2(假设8bit)作为一个16bit的 Num 数据长度而已。
- Addr:从机地址,其中0x00一般为广播包,其他地址可自行设定,若从机收到非本从机地址的数据包则会进行丢包处理。(所以从物理层来看,数据还是“广播”的)
- Cmd:功能码,用于标志该帧功能,常用的有:
功能码
名称
作用
03
读取保持寄存器
在一个或多个保持寄存器中取得当前的二进制值
06
预置单寄存器
把具体二进值装入一个保持寄存器
16
预置多寄存器
把具体的二进制值装入一串连续的保持寄存器
... ... ... 完整的功能码可在附录中查看,为了兼容其他开发者的 ModBus 协议,我们通常采用协议的功能码而不是自定义功能码。
- Reg:寄存器地址,其值为 待发送/读取数据的首地址
- Num:寄存器个数
- Data:数据域
- CRC:校验码,若 CRC 验证错误则会丢包并请求重发
错误帧
Addr(从机地址)
8bit | CMD(功能码)
8bit | Error(错误码)
8bit | CRC(校验位)
16bit |
通讯流程
为简化下文表述,约定如下:
Addr
- 广播地址:0x00
- 从机1:0x01
Cmd
读多个寄存器:0x03
写单个寄存器: 0x06
写多个寄存器:0x10
读错误:0x83
写单个寄存器错误:0x66
写多个寄存器错误:0x90
Reg
温度数据:0x2000
湿度数据:0x2001
待机时间:0x3000
Error
- UnCmd: 0x01
- UnDataAddr:0x02
- UnDataValue:0x03
- CrcErr:0x11
主设备读流程
若存在多从机设备
主机接收到错误帧以后会进行相应的处理,常见的处理是重发。
下面是从机收到读请求帧后,CRC 校验失败的错误帧
主设备写流程
Java 中常用的 Modbus库
外部链接
下为ModBus库链接