本文基于Modbus官方文档进行学习。
在众多学习资料中往往会提到:
Modbus定义了Modbus ASCII、Modbus RTU、Modbus TCP/IP三种基本协议。
但这种看法是不准确的、不本质的。
Modbus确实在不同的物理层和链路层上的实现不同,但是这三种情况在应用层的数据封装上完全一致。其主要区别在于:
'0'
和 'F'
编码二进制 0x0F
。此外,协议规定Modbus协议是一种请求/应答协议,也就意味着无论是哪种Modbus,从站均不能主动向主站发送信息。
此外,主站也可以被叫作Server,从站被叫作Client。
Modbus当前支持的硬件协议:
Modbus官方缩写如下表所示。
ADU | Application Data Unit |
HDLC | High level Data Link Control |
HMI | Human Machine Interface |
IETF | Internet Engineering Task Force |
I/O | Input/Output |
IP | Internet Protocol |
MAC | Medium Access Control |
MB | MODBUS Protocol |
MBAP | MODBUS Application Protocol |
PDU | Protocol Data Unit |
PLC | Programmable Logic Controller |
TCP | Transport Control Protocol |
Modbus提供了一种简单的,可以跨物理层/数据链路层/网络层的通信协议:
Modbus的数据包均遵从如下基本格式:
即:
地址域 | 功能码 | 数据域 | CRC差错校验 |
---|---|---|---|
1Byte | 1Byte | 长度不定,也可能不存在 | 2Byte |
在上图/上表中:
${地址域}${功能码}${数据}${差错校验}
部分被称作ADU(应用数据单元)。${功能码}${数据}
部分被称作PDU(协议数据单元)。在通信模型上:
在数据结构上,Modbus定义了如下四种基础的数据结构:
数据类型 | 读写类型 | ||
---|---|---|---|
离散输入 | 单bit数据 | 只读 | 通常表示 TRUE/FALSE 、 ON/OFF 等 |
线圈 | 单bit数据 | 可读可写 | |
输入寄存器 | 16bit的字 | 只读 | |
保持寄存器 | 16bit的字 | 可读可写 |
为了方便叙述,将上述的16bit称之为 "字" ,即 "word" 。但是要注意并不是所有的CPU平台的 "word" 长度均为16bit。
在报文长度上,由于第一版Modbus的实现限制了ADU和PDU的长度(该版本限制ADU最长256字节),因此:
Modbus在数据编码时采用大端模式。
地址域 | 功能码 | 数据域 | CRC差错校验 |
---|---|---|---|
1Byte | 1Byte | 长度不定,也可能不存在 | 2Byte |
在上述的数据包基本格式中:
在Modbus中的通信过程中:
请求功能码+0x80
),具体可见异常响应章节。地址域 | 功能码 | 数据域 | CRC差错校验 |
---|---|---|---|
1Byte | 1Byte | 长度不定,也可能不存在 | 2Byte |
在上述的数据包基本格式中:
Modbus内置的功能码如下:
功能码 | 操作类型 | ||
---|---|---|---|
读线圈寄存器 | 01 | 位 | 单个或多个 |
读离散线圈寄存器 | 02 | 位 | 单个或多个 |
读保持寄存器 | 03 | 字 | 单个或多个 |
读输入寄存器 | 04 | 字 | 单个或多个 |
写单个线圈寄存器 | 05 | 位 | 单个 |
写单个保持寄存器 | 06 | 字 | 单个 |
读异常状态 | 07 | ||
诊断 | 08 | ||
读通用事件计数器 | 0B | ||
获取通用事件日志 | 0C | ||
写多个线圈寄存器 | 0F | 位 | 多个 |
写多个保持寄存器 | 10 | 字 | 多个 |
回报从站地址 | 11 | ||
读文件记录 | 14 | ||
写文件记录 | 15 | ||
使用AND/OR操作寄存器 | 16 | ||
读写多个寄存器 | 17 | ||
读FIFO队列 | 18 | ||
2B | |||
2B/0D | |||
2B/0E |
注:
正如基本规定中所述:
格式: | 地址域 | 功能码 | 起始地址 高字节 |
起始地址 低字节 |
读取数量 高字节 |
读取数量 低字节 |
CRC校验 |
---|---|---|---|---|---|---|---|
Demo: | 0x01 | 0x01 | 0x02 | 0xC4 | 0x01 | 0x05 | 2Byte |
则上述Demo的含义为:
0x01
的设备上的 0x02C4
地址开始的连续 0x0105
个寄存器Modbus TCP默认端口为502端口。