214 lines
7.9 KiB
Markdown
214 lines
7.9 KiB
Markdown
|
|
# Modbus TCP 协议参考文档
|
|||
|
|
|
|||
|
|
用于 MThings 调试工具配置参考
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 地址划分
|
|||
|
|
|
|||
|
|
Modbus 协议定义了四种数据类型,每种类型有独立的地址空间:
|
|||
|
|
|
|||
|
|
| 类型 | 代码 | 地址范围 | 功能码 | 数据大小 | 访问 | MThings BLOCK |
|
|||
|
|
|------|------|----------|--------|----------|------|---------------|
|
|||
|
|
| Coils (线圈) | 0x | 00001-09999 | 01/05/15 | 1 bit | 读/写 | 0 |
|
|||
|
|
| Discrete Inputs (离散输入) | 1x | 10001-19999 | 02 | 1 bit | 只读 | 1 |
|
|||
|
|
| **Holding Registers (保持寄存器)** | 4x | 40001-49999 | 03/06/16 | 16 bit | 读/写 | **2** |
|
|||
|
|
| Input Registers (输入寄存器) | 3x | 30001-39999 | 04 | 16 bit | 只读 | 3 |
|
|||
|
|
|
|||
|
|
> **注意**: 保持寄存器(Holding Registers)是最常用的类型,MThings 中 BLOCK=2
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 功能码说明
|
|||
|
|
|
|||
|
|
| 功能码 | 名称 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| 01 | Read Coils | 读取线圈状态(位) |
|
|||
|
|
| 02 | Read Discrete Inputs | 读取离散输入状态(位) |
|
|||
|
|
| **03** | **Read Holding Registers** | **读取保持寄存器(最常用)** |
|
|||
|
|
| 04 | Read Input Registers | 读取输入寄存器 |
|
|||
|
|
| 05 | Write Single Coil | 写单个线圈 |
|
|||
|
|
| **06** | **Write Single Register** | **写单个保持寄存器** |
|
|||
|
|
| 15 | Write Multiple Coils | 写多个线圈 |
|
|||
|
|
| **16** | **Write Multiple Registers** | **写多个保持寄存器** |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 错误码说明
|
|||
|
|
|
|||
|
|
当从站无法正常处理请求时,返回异常响应(功能码最高位置1)
|
|||
|
|
|
|||
|
|
| 代码 | 名称 | 说明 | 原因 | 解决方案 |
|
|||
|
|
|------|------|------|------|----------|
|
|||
|
|
| 01 | ILLEGAL_FUNCTION | 非法功能码 | 从站不支持请求的功能码 | 检查功能码是否正确 |
|
|||
|
|
| 02 | ILLEGAL_DATA_ADDRESS | 非法数据地址 | 请求的地址超出有效范围 | 检查起始地址和数量 |
|
|||
|
|
| 03 | ILLEGAL_DATA_VALUE | 非法数据值 | 请求数据包中的值不合法 | 检查写入的数据值 |
|
|||
|
|
| 04 | SLAVE_DEVICE_FAILURE | 从站设备故障 | 从站执行时发生错误 | 检查从站设备状态 |
|
|||
|
|
| 05 | ACKNOWLEDGE | 确认 | 从站需要较长时间处理 | 稍后重新发送请求 |
|
|||
|
|
| 06 | SLAVE_DEVICE_BUSY | 从站设备忙 | 从站正在处理其他命令 | 等待后重试 |
|
|||
|
|
| 08 | MEMORY_PARITY_ERROR | 内存奇偶校验错误 | 从站内存错误 | 检查从站硬件 |
|
|||
|
|
| 0A | GATEWAY_PATH_UNAVAILABLE | 网关路径不可用 | 网关配置错误 | 检查网关配置 |
|
|||
|
|
| 0B | GATEWAY_TARGET_FAILED | 网关目标设备响应失败 | 目标设备未响应 | 检查目标设备是否在线 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Modbus TCP 帧格式
|
|||
|
|
|
|||
|
|
Modbus TCP 在标准 Modbus 帧前添加 MBAP 头:
|
|||
|
|
|
|||
|
|
### MBAP 头 (7 字节)
|
|||
|
|
|
|||
|
|
| 字段 | 字节数 | 说明 |
|
|||
|
|
|------|--------|------|
|
|||
|
|
| Transaction ID | 2 | 事务标识符,用于匹配请求和响应 |
|
|||
|
|
| Protocol ID | 2 | 协议标识符,Modbus 固定为 0x0000 |
|
|||
|
|
| Length | 2 | 后续字节数(单元标识符 + PDU) |
|
|||
|
|
| Unit ID | 1 | 单元标识符(从站地址),TCP 通常为 0 或 1 |
|
|||
|
|
|
|||
|
|
### 示例:读取保持寄存器
|
|||
|
|
|
|||
|
|
**请求**: 读取从站1的地址1000开始的3个寄存器
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
00 01 00 00 00 06 01 03 03 E8 00 03
|
|||
|
|
│ │ │ │ │ │ │ │ │ │ │ │
|
|||
|
|
│ │ │ │ │ │ │ │ │ │ └──┴── 寄存器数量 (3)
|
|||
|
|
│ │ │ │ │ │ │ │ └──┴────── 起始地址 (1000 = 0x03E8)
|
|||
|
|
│ │ │ │ │ │ │ └─────────── 功能码 (03 = 读保持寄存器)
|
|||
|
|
│ │ │ │ │ │ └────────────── 单元ID (从站地址 1)
|
|||
|
|
│ │ │ │ └──┴───────────────── 长度 (6字节)
|
|||
|
|
│ │ └──┴─────────────────────── 协议ID (0x0000 = Modbus)
|
|||
|
|
└──┴───────────────────────────── 事务ID (0x0001)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应**: 返回3个寄存器的值
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
00 01 00 00 00 09 01 03 06 00 01 00 00 00 00
|
|||
|
|
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
|||
|
|
│ │ │ │ │ │ │ │ │ │ │ │ │ └──┴── 寄存器3 (0)
|
|||
|
|
│ │ │ │ │ │ │ │ │ │ │ └──┴────── 寄存器2 (0)
|
|||
|
|
│ │ │ │ │ │ │ │ │ └──┴──────────── 寄存器1 (1)
|
|||
|
|
│ │ │ │ │ │ │ │ └───────────────── 字节数 (6)
|
|||
|
|
│ │ │ │ │ │ │ └──────────────────── 功能码 (03)
|
|||
|
|
│ │ │ │ │ │ └─────────────────────── 单元ID (1)
|
|||
|
|
│ │ │ │ └──┴────────────────────────── 长度 (9字节)
|
|||
|
|
│ │ └──┴──────────────────────────────── 协议ID
|
|||
|
|
└──┴────────────────────────────────────── 事务ID
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 数据类型转换
|
|||
|
|
|
|||
|
|
Modbus 寄存器为 16 位,多字节数据需要多个寄存器:
|
|||
|
|
|
|||
|
|
| 类型 | 寄存器数 | 范围 | 说明 |
|
|||
|
|
|------|----------|------|------|
|
|||
|
|
| UINT16 | 1 | 0 ~ 65535 | 无符号16位整数 |
|
|||
|
|
| INT16 | 1 | -32768 ~ 32767 | 有符号16位整数 |
|
|||
|
|
| UINT32 | 2 | 0 ~ 4294967295 | 无符号32位整数 |
|
|||
|
|
| INT32 | 2 | -2147483648 ~ 2147483647 | 有符号32位整数 |
|
|||
|
|
| FLOAT32 | 2 | IEEE 754 | 单精度浮点数 |
|
|||
|
|
|
|||
|
|
### Float32 示例
|
|||
|
|
|
|||
|
|
值 `50.0` 的 IEEE 754 表示:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
IEEE 754: 0x42480000
|
|||
|
|
|
|||
|
|
大端序 (Big Endian):
|
|||
|
|
寄存器1 (高位): 0x4248
|
|||
|
|
寄存器2 (低位): 0x0000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. MThings 配置参数说明
|
|||
|
|
|
|||
|
|
### BLOCK (数据区域)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 0 | 线圈 Coils (功能码 01/05/15) |
|
|||
|
|
| 1 | 离散输入 Discrete Inputs (功能码 02) |
|
|||
|
|
| **2** | **保持寄存器 Holding Registers (功能码 03/06/16)** |
|
|||
|
|
| 3 | 输入寄存器 Input Registers (功能码 04) |
|
|||
|
|
|
|||
|
|
### PrtcTYPE (数据类型)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 1 | UINT16 - 无符号16位整数 |
|
|||
|
|
| **2** | **FLOAT32 - 32位浮点数** |
|
|||
|
|
| 3 | INT16 - 有符号16位整数 |
|
|||
|
|
| 4 | UINT32 - 无符号32位整数 |
|
|||
|
|
| 5 | INT32 - 有符号32位整数 |
|
|||
|
|
|
|||
|
|
### Size (寄存器数量)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 1 | 1个寄存器 (16位) |
|
|||
|
|
| 2 | 2个寄存器 (32位) |
|
|||
|
|
| 4 | 4个寄存器 (64位) |
|
|||
|
|
|
|||
|
|
### ByteOder (字节序)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 0 | 大端序 Big Endian (高字节在前) - **常用** |
|
|||
|
|
| 1 | 小端序 Little Endian (低字节在前) |
|
|||
|
|
|
|||
|
|
### WordOder (字序)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 0 | 高字在前 - **常用** |
|
|||
|
|
| 1 | 低字在前 |
|
|||
|
|
|
|||
|
|
### ShowType (显示类型)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 0 | 浮点数显示 |
|
|||
|
|
| 1 | 十六进制显示 |
|
|||
|
|
| 2 | 十进制显示 |
|
|||
|
|
| 3 | 二进制显示 |
|
|||
|
|
|
|||
|
|
### LinkMode (连接模式)
|
|||
|
|
|
|||
|
|
| 值 | 说明 |
|
|||
|
|
|----|------|
|
|||
|
|
| 0 | TCP Client 模式 |
|
|||
|
|
| 1 | TCP Server 模式 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 常见问题
|
|||
|
|
|
|||
|
|
### Q1: 为什么读取的数据全是0?
|
|||
|
|
**A**: 检查地址是否正确,注意有些设备地址从0开始,有些从1开始。
|
|||
|
|
|
|||
|
|
### Q2: 为什么连接超时?
|
|||
|
|
**A**: 检查IP地址和端口是否正确,防火墙是否放行502端口。
|
|||
|
|
|
|||
|
|
### Q3: 为什么浮点数显示不正确?
|
|||
|
|
**A**: 检查字节序(ByteOder)和字序(WordOder)设置,不同厂商可能使用不同的字节序。
|
|||
|
|
|
|||
|
|
### Q4: 返回异常码02是什么意思?
|
|||
|
|
**A**: 非法数据地址(ILLEGAL_DATA_ADDRESS),请求的地址超出设备有效范围。
|
|||
|
|
|
|||
|
|
### Q5: 如何区分功能码03和04?
|
|||
|
|
**A**:
|
|||
|
|
- 功能码03:读取保持寄存器(Holding Registers),可读写
|
|||
|
|
- 功能码04:读取输入寄存器(Input Registers),只读
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 参考资料
|
|||
|
|
|
|||
|
|
- Modbus 官方规范: [modbus.org](https://modbus.org/specs.php)
|
|||
|
|
- MThings 使用手册: `Tools/MThings/MThings使用手册.pdf`
|