4. 数据帧结构:起始符、地址域、功能码、数据域、校验域、结束符详解

在 Stream 4 Function 1 协议中,设备参数读写的底层通信完全依赖 数据帧 进行。一个完整的数据帧由六个固定域按顺序组成:起始符、地址域、功能码、数据域、校验域、结束符。理解每一域的字节长度、取值范围和功能,是正确解析报文、避免通信故障的前提。

核心原则: 数据帧是“一问一答”的基础单元。主机发送请求帧,从机回复响应帧。两帧的结构完全一致,但数据域内容不同。

4.1 数据帧总体结构

下表展示了标准数据帧的字节布局(以十六进制表示):

域名称 字节数 固定值 / 范围 说明
起始符 1 字节 0xAA 帧起始标记,接收方以此判断报文开始
地址域 1 字节 0x01 ~ 0xF7 目标从机设备地址(广播地址 0x00 保留)
功能码 1 字节 0x03 / 0x06 / 0x10 指示操作类型:读、写单寄存器、写多寄存器
数据域 N 字节 变长(0 ~ 252 字节) 包含寄存器地址、数量、数据值等核心信息
校验域 2 字节 CRC-16 (Modbus) 对整个帧(起始符之后、校验域之前)进行循环冗余校验
结束符 1 字节 0x55 帧结束标记,接收方以此判断报文结束
提示: 起始符 0xAA 和结束符 0x55 是二进制互补模式(10101010 ↔ 01010101),这种设计有助于硬件级帧同步和抗干扰。

4.2 各域详解

4.2.1 起始符(Start Byte)

固定为 0xAA。接收设备在空闲状态持续监听总线,一旦检测到 0xAA,立即启动帧接收流程。如果起始符错误,整帧将被丢弃。

4.2.2 地址域(Address Field)

  • 范围: 0x01 ~ 0xF7(1 ~ 247),对应 247 个可能的从机地址。
  • 广播地址: 0x00 保留用于主机向所有从机发送广播命令,从机不应答。
  • 地址冲突: 同一总线上不允许两个从机使用相同地址,否则会导致数据碰撞和通信异常。

4.2.3 功能码(Function Code)

功能码决定了本次通信的操作类型。Stream 4 Function 1 协议主要使用以下三种:

功能码 名称 操作 数据域典型结构
0x03 读保持寄存器 读取从机 1 个或多个连续参数 起始地址(2B) + 寄存器数量(2B)
0x06 写单个寄存器 写入单个参数值 寄存器地址(2B) + 数据值(2B)
0x10 写多个寄存器 批量写入连续参数 起始地址(2B) + 数量(2B) + 字节数(1B) + 数据(NB)

4.2.4 数据域(Data Field)

数据域是帧的“有效载荷”,长度可变。根据功能码不同,数据域包含:

  • 寄存器地址: 2 字节,高字节在前(Big-Endian),范围 0x0000 ~ 0xFFFF。
  • 寄存器数量: 2 字节,表示连续读/写的寄存器个数。
  • 数据值: 每个寄存器占 2 字节,高字节在前。
  • 字节计数: 仅写多寄存器命令(0x10)包含,表示后续数据的总字节数。

4.2.5 校验域(CRC Field)

采用 CRC-16 (Modbus) 算法,校验范围从地址域开始到数据域结束(不包含起始符和结束符)。生成多项式为 0x8005,初始值为 0xFFFF。校验码低字节在前,高字节在后。

常见错误: 很多初学者将 CRC 计算范围误包含起始符或结束符,导致校验失败。请牢记:CRC 只校验 地址域 + 功能码 + 数据域。

4.2.6 结束符(End Byte)

固定为 0x55。接收方在收到 0x55 后,立即对已接收数据进行 CRC 校验,并判断帧是否完整。如果结束符错误,帧将被丢弃并触发超时重传。

4.3 数据帧结构示意图

下图以图形方式展示了完整数据帧的字节排列和每个域的作用:

Stream 4 Function 1 数据帧结构 起始符 0xAA 地址域 0x01~0xF7 功能码 0x03/0x06/0x10 数据域 N 字节(变长) 校验域 CRC-16 结束符 0x55 CRC 校验范围(不包含起始符和结束符) 说明: • 起始符 0xAA 和结束符 0x55 是帧同步标记,不参与 CRC 计算。 • 地址域、功能码、数据域共同构成 CRC 校验的输入数据。 • 数据域长度可变,最大 252 字节,保证整帧不超过 256 字节。

4.4 完整帧示例

以下是一个实际读参数请求帧的逐字节解析:

请求帧(主机 → 从机,读取地址 0x0002 开始的 3 个寄存器):
AA  01  03  00  02  00  03  CRC_L  CRC_H  55

字节分解:
AA        → 起始符
01        → 地址域(从机地址 1)
03        → 功能码(读保持寄存器)
00 02     → 数据域:起始寄存器地址(高字节 0x00,低字节 0x02)
00 03     → 数据域:寄存器数量(3 个)
CRC_L CRC_H → 校验域(低字节在前,高字节在后)
55        → 结束符
响应帧(从机 → 主机,返回 3 个寄存器的值):
AA  01  03  06  00 1A  00 2B  00 3C  CRC_L  CRC_H  55

字节分解:
AA        → 起始符
01        → 地址域(从机地址 1)
03        → 功能码(读保持寄存器)
06        → 数据域:后续数据字节数(3 个寄存器 × 2 字节 = 6 字节)
00 1A     → 数据域:寄存器 0x0002 的值(0x001A = 26)
00 2B     → 数据域:寄存器 0x0003 的值(0x002B = 43)
00 3C     → 数据域:寄存器 0x0004 的值(0x003C = 60)
CRC_L CRC_H → 校验域
55        → 结束符
实战建议: 使用串口调试工具抓取报文时,先确认起始符 0xAA 和结束符 0x55 是否正确,再解析中间部分。如果 CRC 校验失败,优先检查地址域和功能码是否被错误修改。

4.5 常见错误与避坑指南

错误类型 现象 原因 解决方案
起始符错误 从机无响应 总线干扰导致 0xAA 被篡改 增加硬件滤波,检查总线终端电阻
地址不匹配 从机无响应 请求帧地址域与从机配置地址不一致 核对从机拨码开关或软件地址设置
功能码不支持 从机返回异常码 0x01 使用了协议未定义的功能码 仅使用 0x03、0x06、0x10
CRC 计算错误 从机无响应或返回异常码 0x04 校验范围错误或算法实现有误 确认 CRC 只覆盖地址域+功能码+数据域
结束符错误 帧被丢弃,超时重传 总线噪声或字节丢失导致 0x55 错误 增加帧超时时间,检查通信线缆屏蔽
重要提醒: 在编写通信程序时,务必对接收到的每一帧进行 起始符验证、地址匹配、CRC 校验 和 结束符验证。任何一步失败都应立即丢弃该帧,避免错误数据写入设备参数。