跳转至

Modbus 响应数据结构详解 📨

响应结构概述

本文档详细说明 Modbus 协议中各种功能码的响应数据结构,包括正常响应和异常响应的完整格式说明。

📋 响应格式总览

正常响应结构

每种功能码的正常响应都包含特定的字段结构:

通用结构:

[从站地址] [功能码] [字节计数] [数据] [校验]

特点:

  • 包含字节计数字段,指示后续数据长度
  • 数据部分根据功能码类型有所不同
  • 校验方式取决于传输模式(RTU/ASCII/TCP)

通用结构:

[从站地址] [功能码] [地址/数据] [校验]

特点:

  • 单个写入:回显请求内容
  • 多个写入:返回起始地址和数量确认
  • 无字节计数字段

异常响应结构

通用异常响应格式:

[从站地址] [异常功能码] [异常码] [校验]

其中:

  • 异常功能码 = 原功能码 + 0x80
  • 异常码 = 具体的错误代码

🔍 详细响应解析

读取功能码响应

01 - 读线圈状态响应

[地址] [01] [字节计数] [线圈状态字节1] [线圈状态字节2] ... [CRC]

示例:

01 01 02 55 A9 B8 FA

解析:

  • 01: 从站地址
  • 01: 功能码
  • 02: 字节计数(2字节数据)
  • 55 A9: 线圈状态数据
  • B8 FA: CRC校验
:[地址][01][字节计数][线圈状态数据][LRC]<CR><LF>

示例:

:01010255A9B8<CR><LF>
[MBAP头] [01] [字节计数] [线圈状态字节1] [线圈状态字节2] ...

02 - 读离散输入状态响应

[地址] [02] [字节计数] [输入状态字节1] [输入状态字节2] ... [CRC]

示例:

01 02 01 55 B8 FA

解析:

  • 01: 从站地址
  • 02: 功能码
  • 01: 字节计数(1字节数据)
  • 55: 输入状态数据
  • B8 FA: CRC校验

03 - 读保持寄存器响应

[地址] [03] [字节计数] [寄存器1高] [寄存器1低] [寄存器2高] [寄存器2低] ... [CRC]

示例:

01 03 04 00 0A 00 0B B8 FA

解析:

  • 01: 从站地址
  • 03: 功能码
  • 04: 字节计数(4字节数据)
  • 00 0A: 第一个寄存器值(10)
  • 00 0B: 第二个寄存器值(11)
  • B8 FA: CRC校验

04 - 读输入寄存器响应

[地址] [04] [字节计数] [寄存器1高] [寄存器1低] [寄存器2高] [寄存器2低] ... [CRC]

示例:

01 04 02 13 88 B8 FA

解析:

  • 01: 从站地址
  • 04: 功能码
  • 02: 字节计数(2字节数据)
  • 13 88: 寄存器值(5000)
  • B8 FA: CRC校验

写入功能码响应

05 - 写单个线圈响应

[地址] [05] [线圈地址高] [线圈地址低] [线圈值高] [线圈值低] [CRC]

示例:

01 05 00 01 FF 00 8C 3A

解析:

  • 01: 从站地址
  • 05: 功能码
  • 00 01: 线圈地址(1)
  • FF 00: 线圈值(ON)
  • 8C 3A: CRC校验

06 - 写单个寄存器响应

[地址] [06] [寄存器地址高] [寄存器地址低] [寄存器值高] [寄存器值低] [CRC]

示例:

01 06 00 01 00 03 89 CA

解析:

  • 01: 从站地址
  • 06: 功能码
  • 00 01: 寄存器地址(1)
  • 00 03: 寄存器值(3)
  • 89 CA: CRC校验

15 - 写多个线圈响应

[地址] [0F] [起始地址高] [起始地址低] [线圈数量高] [线圈数量低] [CRC]

示例:

01 0F 00 00 00 0A 25 CD

解析:

  • 01: 从站地址
  • 0F: 功能码
  • 00 00: 起始地址(0)
  • 00 0A: 线圈数量(10)
  • 25 CD: CRC校验

16 - 写多个寄存器响应

[地址] [10] [起始地址高] [起始地址低] [寄存器数量高] [寄存器数量低] [CRC]

示例:

01 10 00 00 00 02 C4 0B

解析:

  • 01: 从站地址
  • 10: 功能码
  • 00 00: 起始地址(0)
  • 00 02: 寄存器数量(2)
  • C4 0B: CRC校验

诊断功能码响应

08 - 诊断响应

[地址] [08] [子功能码高] [子功能码低] [数据] ... [CRC]

示例 - 返回查询数据:

01 08 00 00 12 34 56 78 9A BC

解析:

  • 01: 从站地址
  • 08: 功能码
  • 00 00: 子功能码(返回查询数据)
  • 12 34 56 78 9A BC: 诊断数据

17 - 报告从站ID响应

[地址] [11] [字节计数] [从站ID数据] [运行状态] [CRC]

示例:

01 11 06 4D 6F 64 62 75 73 00 8C 3A

解析:

  • 01: 从站地址
  • 11: 功能码
  • 06: 字节计数(6字节数据)
  • 4D 6F 64 62 75 73: 从站ID("Modbus")
  • 00: 运行状态(运行中)
  • 8C 3A: CRC校验

⚠️ 异常响应详解

异常码说明

异常码 名称 描述 可能原因
01 非法功能码 接收到的功能码不被支持 功能码超出从站支持范围
02 非法数据地址 接收到的数据地址不被允许 地址超出从站地址范围
03 非法数据值 接收到的数据值不被允许 数据值超出允许范围
04 从站设备故障 从站在处理请求时发生不可恢复的错误 从站内部错误
05 确认 从站已接受请求并正在处理 长时间操作正在进行
06 从站设备忙 从站正在处理长时间程序命令 从站忙,稍后重试
07 负确认 从站无法执行程序功能 程序执行失败
08 内存奇偶错误 从站检测到扩展内存奇偶错误 内存硬件故障

异常响应示例

[地址] [异常功能码] [异常码] [CRC]

示例 - 非法功能码:

01 81 01 C0 B1

解析:

  • 01: 从站地址
  • 81: 异常功能码(0x01 + 0x80)
  • 01: 异常码(非法功能码)
  • C0 B1: CRC校验
:[地址][异常功能码][异常码][LRC]<CR><LF>

示例:

:018101C0<CR><LF>
[MBAP头] [异常功能码] [异常码]

示例:

00 01 00 00 00 03 01 81 01

🔧 数据解析技巧

位数据解析

线圈和离散输入状态按位打包:

  • 每个字节包含8个位状态
  • LSB(最低有效位)对应最小地址
  • 位顺序: bit0 → bit7 (bit0 = LSB)

示例解析:

字节值: 0x55 (二进制: 01010101)
位状态: bit0=1, bit1=0, bit2=1, bit3=0, bit4=1, bit5=0, bit6=1, bit7=0

寄存器数据解析

字节序处理:

  • Modbus 使用大端序(高字节在前)
  • 16位寄存器: [高字节] [低字节]
  • 32位数据: 通常由两个连续寄存器组成

数据类型转换:

value = (high_byte << 8) | low_byte
1
2
3
value = (high_byte << 8) | low_byte
if value >= 0x8000:
    value = value - 0x10000
1
2
3
import struct
bytes_data = bytes([high1, low1, high2, low2])
value = struct.unpack('>f', bytes_data)[0]  # 大端序浮点数

错误检测与处理

CRC校验验证:

1
2
3
def verify_crc(data, crc_received):
    calculated_crc = crc16(data)
    return calculated_crc == crc_received

LRC校验验证:

1
2
3
def verify_lrc(data, lrc_received):
    calculated_lrc = lrc_check(data)
    return calculated_lrc == lrc_received

📊 响应时序要求

串行传输时序

字符间超时

  • 定义: 1.5个字符时间
  • 计算: 1.5 × (1 + 数据位 + 停止位 + 奇偶位) / 波特率
  • 用途: 检测字符传输中断

帧间间隔

  • 定义: 3.5个字符时间
  • 计算: 3.5 × (1 + 数据位 + 停止位 + 奇偶位) / 波特率
  • 用途: 区分不同数据帧

响应超时处理

典型超时设置:

  • 串行通信: 1-5秒
  • TCP通信: 5-30秒
  • 具体值: 根据网络条件和设备性能调整

超时处理策略:

  1. 重试机制(最多3次)
  2. 指数退避算法
  3. 连接状态检查
  4. 错误日志记录

🔍 调试技巧

常见问题排查

可能原因:

  • 物理连接问题
  • 从站地址错误
  • 波特率不匹配
  • 从站设备故障

排查步骤:

  1. 检查物理连接
  2. 验证从站地址
  3. 确认通信参数
  4. 检查从站状态

可能原因:

  • 数据传输干扰
  • 波特率不匹配
  • 硬件故障
  • 软件实现错误

排查步骤:

  1. 检查线路质量
  2. 验证波特率设置
  3. 检查CRC算法实现
  4. 使用示波器分析信号

可能原因:

  • 功能码不支持
  • 地址超出范围
  • 数据值无效
  • 从站忙

排查步骤:

  1. 检查异常码含义
  2. 验证地址范围
  3. 确认数据有效性
  4. 重试或等待

调试工具使用

串口调试助手:

  • 实时监控数据收发
  • 十六进制显示
  • 自动CRC计算

Wireshark:

  • 网络包分析
  • 协议解析
  • 时序分析

专业Modbus工具:

  • ModbusPoll
  • ModbusSlave
  • 自动化测试

总结

掌握 Modbus 响应数据结构的详细解析方法,能够帮助你快速定位和解决通信问题,提高系统开发和维护效率。

相关文档: