2. Modbus RTU模式详解:RTU帧结构、传输规则与时间间隔

各位工程师朋友,咱们今天来聊聊Modbus RTU模式。说实话,RTU模式是工业现场用得最多的,没有之一。我这些年调试过的仪表,十台里有七八台都是走RTU。为什么?因为它简单、可靠,对硬件要求低。

但越是简单的东西,越容易在细节上翻车。我记得刚入行那会儿,就因为帧间隔没算对,折腾了一整天才找到问题。好,咱们开始。

2.1 RTU帧结构

一个完整的RTU报文,说白了就是四段:地址码、功能码、数据区、CRC校验。我习惯把这四个部分叫做“一帧四段”。

字段 长度 说明
地址码 1字节 从站地址,范围1~247
功能码 1字节 操作类型,如03读保持寄存器
数据区 N字节 寄存器地址、数量、数据值
CRC校验 2字节 低字节在前,高字节在后

地址码

地址码就一个字节,范围0~247。0是广播地址,所有从站都得响应。1~247是单播地址。我建议你给设备分配地址时,别用1、2、3这种太连续的,容易搞混。我曾经在一个项目里,两台设备都设成了地址5,结果主站发命令,两台一起响应,数据全乱了。

功能码

功能码定义了你要干什么。常用的就那几个:01读线圈、02读离散输入、03读保持寄存器、04读输入寄存器、05写单个线圈、06写单个寄存器。嗯,这里要注意,有些仪表厂商会自定义功能码,比如65、66这种。遇到这种情况,你得仔细看手册,别想当然。

数据区

数据区是报文里最灵活的部分。读操作时,数据区包含起始地址和读取数量。写操作时,数据区包含地址和要写的数据。举个例子,读地址0开始的3个保持寄存器:

请求:01 03 00 00 00 03 05 CB
响应:01 03 06 00 01 00 02 00 03 3A 9C

请求报文里,00 00是起始地址,00 03是数量。响应报文里,06是数据字节数,后面6个字节就是三个寄存器的值。你看,是不是很直观?

CRC校验

CRC校验是RTU模式的灵魂。它用16位循环冗余校验,多项式是0x8005。计算时,低字节在前,高字节在后。我见过不少新手,CRC算错了,报文发出去石沉大海。

CRC计算要点:

  • 初始值:0xFFFF
  • 多项式:0xA001(反转后的0x8005)
  • 结果异或:0x0000
  • 发送顺序:低字节先发

我个人习惯用查表法算CRC,速度快,适合嵌入式。如果你用PLC,很多厂家都提供了现成的CRC函数,直接调用就行。

2.2 RTU报文传输规则

RTU模式是半双工通信,主站问,从站答。规则很简单:

  • 主站发送请求帧
  • 从站接收并解析
  • 从站发送响应帧
  • 主站接收响应

这里有个坑:从站必须在收到完整帧后的规定时间内响应。如果超时,主站会认为从站故障。我曾经调试一个温控仪表,它响应时间要200ms,而主站超时设了100ms,结果一直报错。后来把超时改成500ms,问题就解决了。

注意:从站响应超时时间一般建议设为500ms~1000ms。如果网络中有多个从站,超时时间要适当加长。

2.3 字符间隔与帧间隔

这是RTU模式最容易出问题的地方。为什么?因为时间参数设不对,报文就解析错了。

字符间隔

字符间隔是指同一帧内,两个字节之间的最大时间间隔。标准规定:

  • 波特率≤19200bps:间隔≤1.5个字符时间
  • 波特率>19200bps:间隔≤750μs

1.5个字符时间怎么算?举个例子,9600波特率,1个起始位+8个数据位+1个停止位=10位。1个字符时间=10/9600≈1.04ms。1.5个字符时间≈1.56ms。也就是说,同一帧内两个字节的间隔不能超过1.56ms。

你想想看,如果间隔超过了这个值,从站就会认为帧结束了,然后开始解析。结果呢?数据不全,CRC校验失败,报文就丢了。

帧间隔

帧间隔是指两帧之间的最小间隔。标准规定:

  • 波特率≤19200bps:间隔≥3.5个字符时间
  • 波特率>19200bps:间隔≥1.75ms

还是9600波特率,3.5个字符时间≈3.64ms。也就是说,发完一帧后,至少要等3.64ms才能发下一帧。

我的经验:实际项目中,我习惯把帧间隔设得比标准值大一点,比如5个字符时间。这样能避免一些硬件延迟带来的问题。特别是用无线数传电台时,帧间隔要更大,因为电台有收发切换时间。

2.4 知识体系结构图

下面这张图,是我自己画的RTU模式知识结构。你看一眼,心里就有数了。

Modbus RTU模式知识体系 帧结构 传输规则 时间间隔 地址码 功能码 数据区 CRC校验 主站请求 → 从站响应 半双工通信 超时处理机制 字符间隔 ≤1.5字符 帧间隔 ≥3.5字符 波特率影响计算 关键参数:波特率、数据位、停止位、校验位 注意:波特率≤19200bps时,时间参数按字符时间计算 波特率>19200bps时,使用固定时间值

2.5 避坑指南

最后,我把自己踩过的坑总结一下,你遇到了可以少走弯路。

我曾经犯过的错:

  • CRC计算时搞错了字节顺序,低字节发成了高字节
  • 帧间隔设得太小,导致从站把两帧当成一帧解析
  • 地址码用了0,以为能广播,结果从站没响应
  • 功能码用了不支持的,从站返回异常码,我没处理

嗯,RTU模式就这些内容。你只要把帧结构记牢,时间参数算对,传输规则搞清楚,调试起来基本不会有大问题。下次咱们聊ASCII模式,那个又是另一套玩法了。


公众号:蓝海资料掘金营,微信deep3321