4、报文结构详解:RTU帧格式、ASCII帧格式、TCP报文格式
各位工程师,咱们今天聊点实在的。报文结构这东西,说白了就是设备之间交流的“黑话”。你想想看,两个设备要通信,总得有个约定好的格式吧?谁先说、说什么、说完了怎么校验,都得定死。我这些年调试下来,发现很多现场问题,追根溯源都是报文格式没搞对。
嗯,咱们直接进入正题。Modbus 最常用的三种报文格式:RTU、ASCII 和 TCP。我一个个拆开来讲。
4.1 RTU 帧格式:现场最常用的“硬汉”
RTU 格式,我个人习惯叫它“二进制硬汉”。为什么?因为它紧凑、高效,不跟你玩虚的。在风电现场,绝大多数从站设备(比如变桨控制器、变频器)都默认用 RTU。
一个完整的 RTU 帧长这样:
| 地址码 (1字节) | 功能码 (1字节) | 数据区 (N字节) | CRC校验 (2字节) |
咱们拆开看:
- 地址码:1个字节,范围 1-247。0 是广播地址,所有设备都得听,但不回复。我在项目中遇到过,有人把从站地址设成了 0,结果主站死活收不到回应,查了半天才发现是地址冲突。
- 功能码:1个字节,告诉从站你要干嘛。比如 0x03 是读保持寄存器,0x06 是写单个寄存器。这个别搞错,搞错了从站会回异常码。
- 数据区:长度可变,具体看功能码。比如读寄存器时,这里放起始地址和寄存器数量。
- CRC校验:2个字节,循环冗余校验。这是 RTU 的“防伪标识”,算错了从站直接不理你。
关键点:RTU 帧没有起始位和结束位,靠的是总线空闲时间来判断帧边界。一般要求 3.5 个字符时间以上无数据,就算一帧结束。这个时间跟波特率有关,9600 波特率下大约是 3.5ms。
我的经验:调试时如果发现从站没反应,先别急着怀疑代码。拿示波器抓一下总线,看看帧间隔时间对不对。我曾经在某个风场,就因为主站发的帧间隔太短,从站一直把两帧当成一帧处理,折腾了一下午。
4.2 ASCII 帧格式:看得见但效率低
ASCII 格式,说白了就是把 RTU 的二进制数据转成可读的 ASCII 字符。每个字节拆成两个十六进制字符发送,比如 0x1A 就发 '1' 和 'A'。
帧格式如下:
| 起始符 ':' (0x3A) | 地址码 (2字符) | 功能码 (2字符) | 数据区 (N字符) | LRC校验 (2字符) | 结束符 CR+LF |
特点很明显:
- 起始符:固定是冒号 ':',告诉从站“我要开始说话了”。
- 地址码、功能码、数据区:都是 ASCII 字符,每个字节用两个字符表示。
- LRC校验:纵向冗余校验,比 CRC 简单,但可靠性也差一些。
- 结束符:回车换行 (0x0D + 0x0A)。
注意:ASCII 格式的传输效率只有 RTU 的一半左右。同样发 10 个字节的数据,RTU 只要 14 个字节,ASCII 要 28 个字符(加上起始结束符更多)。所以风电现场很少用 ASCII,除非是老旧设备或者调试阶段为了方便看日志。
为什么会有人用 ASCII?我个人觉得,主要是调试时方便。你拿串口助手一看,'3A 30 31 30 33...' 一眼就能看出地址是 01,功能码是 03。RTU 的话,0x01 0x03 你得心里换算一下。
4.3 TCP 报文格式:以太网时代的“新贵”
现在越来越多的风电设备开始支持以太网通信,Modbus TCP 也就成了标配。它跟 RTU 最大的区别是:没有了 CRC 校验,换成了 MBAP 头。为什么?因为 TCP/IP 协议栈自己会做校验,Modbus 就不需要重复劳动了。
TCP 报文格式:
| MBAP头 (7字节) | 功能码 (1字节) | 数据区 (N字节) |
MBAP 头(Modbus Application Protocol Header)包含:
| 字段 | 长度 | 说明 |
|---|---|---|
| 事务处理标识符 | 2字节 | 用于匹配请求和响应,一般每次通信加1 |
| 协议标识符 | 2字节 | 固定为 0x0000,表示 Modbus 协议 |
| 长度 | 2字节 | 后续字节数(功能码+数据区) |
| 单元标识符 | 1字节 | 相当于 RTU 的地址码,用于网关路由 |
注意:TCP 报文里没有 CRC,但多了 MBAP 头。这个头里的“长度”字段特别重要,它告诉接收方“你还要读多少字节才算完”。我见过有人把这个长度算错了,导致接收方一直等数据,最后超时。
嗯,这里有个容易踩的坑:单元标识符。在直连 TCP 设备时,这个值一般设为 0xFF 或 0x00。但如果你通过网关连接 RTU 从站,这个值就得填 RTU 从站的地址。我曾经在调试一个风场 SCADA 系统时,网关后面挂了 10 个变桨控制器,单元标识符填错了,结果主站只能跟第一个设备通信,后面的全不理我。
4.4 三种格式对比:一张图看懂
为了让你更直观地理解,我画了张对比图。三种格式的核心区别一目了然:
我的建议:如果你刚开始接触 Modbus,先从 RTU 入手。它最常用,也最能锻炼你对报文的理解。TCP 其实更简单,但前提是你得懂 TCP/IP 基础。ASCII 嘛,除非你遇到老古董设备,否则基本用不上。
好了,报文结构就讲到这里。三种格式各有各的适用场景,RTU 是现场之王,TCP 是未来趋势,ASCII 是调试利器。你只要记住它们的核心区别:RTU 靠 CRC 和空闲时间判断帧边界,ASCII 靠起始结束符,TCP 靠 MBAP 头里的长度字段。下次调试时遇到问题,先检查报文格式对不对,能省下不少时间。