ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Modbus RTU读寄存器耗时计算:从波特率到轮询周期完整指南

2026/9/18 8:36:21 拓冰建站 浏览量
Modbus RTU读寄存器耗时计算:从波特率到轮询周期完整指南 调试 RS485 总线上的 Modbus RTU 设备时几乎每一个项目都会在同一个问题上卡住我发出了一条读寄存器的命令到底要等多久才能收到数据这个问题听着简单可真要回答光靠“应该挺快吧”完全不够用。它直接决定了你后面怎么选波特率、怎么定超时时间、怎么安排多站轮询周期也决定了你在现场看到波形和延迟数据时心里有没有底。我见过不少同行在调 32 台变频器或者几十块仪表时把轮询周期拍脑袋设成 200ms结果总线忙不过来通讯频繁超时。还有一些人把超时设得太短设备处理稍慢一点就重发把原本能跑通的网络搞得一团糟。这类问题的根子往往不是设备和线路而是没有先把读寄存器的耗时从理论上算清楚。这篇文章就把这件事从头到尾捋一遍。我不绕弯子直接给你能用的公式、对照表和计算过程最后再说说实测和理论对不上的时候到底该怀疑哪里。1. 两个地基参数波特率与单字节传输时间1.1 bit 时间怎么换算别把 10bit 和 11bit 搞混一切耗时计算的地基是波特率。波特率 9600意思是每秒在 RS485 差分线上传输 9600 个 bit。那么一个 bit 占用的时间就是Tbit 1 / 9600 ≈ 104.17 微秒波特率 19200 时Tbit ≈ 52.08 微秒波特率 115200 时Tbit ≈ 8.68 微秒。这个换算本身很简单但实际项目里真正的坑在于一个字节在串口线上不是只占 8 个 bit。标准 UART 发送一个字节时会先发一个起始位逻辑 0然后发送 8 个数据位后面可能跟校验位最后是停止位逻辑 1。所以一个字符帧的实际长度是8N18 数据位无校验1 停止位1 8 0 1 10 bit8E18 数据位偶校验1 停止位1 8 1 1 11 bit8N28 数据位无校验2 停止位1 8 0 2 11 bit很多人在计算时默认一个字节等于 10 bit这没错但只对 8N1 成立。如果你的从站设备出厂配置是 8E1那单字节时间就要按 11 bit 来算两者相差 10%。在一帧报文只有几个字节时看不出差异但在轮询几十台设备、每天运行几个小时后误差会被放大最终导致你估算的扫描周期比实际偏短。以 9600 波特率为例我用一张表把常见配置的单字节时间列出来后面所有帧耗时都能直接查串口配置单字节 bit 数9600 下单字节时间19200 下单字节时间115200 下单字节时间8N1101.0417 ms0.5208 ms0.0868 ms8E1111.1458 ms0.5729 ms0.0955 ms8N2111.1458 ms0.5729 ms0.0955 ms1.2 先确认从站实际参数再谈理论计算每一款设备出厂时的串口格式都可能不同。老式仪表和部分国产电量表喜欢用 8E1变频器里 8N1 和 8N2 都很常见一些 PLC 的串口模块通过 DIP 拨码开关切换停止位和校验位。所以拿到一个新设备不要一上来就按 10bit 去算先到设备手册或参数菜单里确认它的数据格式。我记得调过一台进口温控器手册上写默认 9600, 8E1配置界面里看不到停位设置。当时按 8N1 估算轮询周期结果现场总是慢大约 10%。最后用示波器抓波形发现每个字节尾部都多了一段校验位时间这才意识到是 8E1。把那 10% 补上以后周期估算和实测就对上了。基础公式可以统一写成TB 单字节 bit 数 / 波特率其中“单字节 bit 数”就是上面表格里的 10 或者 11。这是后面所有耗时计算的唯一乘法因子。2. 03 功能码的帧结构请求 8 字节、响应 52N 字节2.1 请求帧读保持寄存器为什么固定 8 个字节Modbus RTU 读保持寄存器最常用的功能码是 030x03。主站发给从站的请求帧如下字段字节数说明从站地址1目标设备地址范围 1~247功能码10x03读保持寄存器起始寄存器地址2高字节在前寄存器数量2高字节在前范围 1~125CRC162低字节在前整个请求帧固定 8 字节和你要读多少个寄存器无关。原因很好理解主站只需要告诉从站“从哪个地址开始读、读多少”寄存器内容本身不放在请求里。需要注意 CRC 的字节序与地址字段相反是低字节在前。这在解析报文时很关键但在耗时计算中不需要单独区分反正都是两字节按顺序排队发送。2.2 响应帧为什么随寄存器数量线性增长从站收到请求并校验通过后返回的响应帧是这样组成的字段字节数说明从站地址1同请求地址功能码10x03正常响应字节数1数据区总字节数等于寄存器数 × 2寄存器数据N × 2N 个寄存器每个占 2 字节CRC162低字节在前响应帧总字节数 1 1 1 2N 2 5 2N。所以读 1 个寄存器时响应是 7 字节读 10 个寄存器时响应是 25 字节读 32 个寄存器时响应是 69 字节读 125 个寄存器时响应是 255 字节。2.3 帧耗时对照表直接查知道了字节数再乘上单字节时间 TB就得到总线占用时间。下表以 8N1 配置为例列出了常见读取数量下的帧耗时读取寄存器数 N请求帧耗时 (9600)响应帧耗时 (9600)响应帧耗时 (19200)响应帧耗时 (115200)18.33 ms7.29 ms3.65 ms0.61 ms48.33 ms13.54 ms6.77 ms1.13 ms108.33 ms26.04 ms13.02 ms2.17 ms328.33 ms71.88 ms35.94 ms5.99 ms1258.33 ms265.63 ms132.81 ms22.14 ms从这张表能看出一个很实用的小结论在 9600 波特率下如果一次读 32 个寄存器光响应帧就要 72ms再加上请求和帧间隔单轮就要接近 90ms。很多项目里轮询周期设得太短正是因为没有意识到 9600 下传这么多字节需要这么长时间。3. 一次完整读操作的六段时间链3.1 帧间静默时间 t3.5要算两次不是一次Modbus RTU 协议规定报文帧之间必须有至少 3.5 个字符时间的静默间隔。这个静默的作用是让接收方识别“上一个帧已经结束接下来是一个新帧”。如果帧内两个字节之间的间隔超过 1.5 个字符时间接收方会认为帧不完整直接丢弃。t3.5 的计算公式是T3.5 3.5 × TB以 9600、8N1 为例T3.5 3.5 × 1.0417 ≈ 3.65ms。19200 下约 1.82ms115200 下约 0.30ms。很多人算轮询周期时只算一次 t3.5这是错的。一次完整的“请求-响应”过程里至少有两次帧间静默一次在请求帧发完后、从站开始响应前另一次在响应帧发完后、主站开始下一次轮询前。如果你想模拟一个持续运行的轮询循环这两次都要计入总时间。3.2 从站处理时延不同设备的差异能到百倍从站收到完整请求帧后并不是立刻就能把响应发出来。它要解析功能码、查寄存器表、组帧、计算 CRC这些都需要时间。不同设备的处理时延差异极大我整理了一张经验参考表从站设备类型典型处理时延范围简易单片机从站裸机查询式处理1~3 ms带 RTOS 任务调度的从站5~20 ms常见电量仪表2~10 ms变频器10~50 ms个别可能到 100 ms老旧 PLC 串口模块20~80 ms这张表只能作为预估参考具体数值必须通过实测确认。实测方法不复杂用 Modbus Poll 或串口助手记录请求发出的时间点和响应首个字节到达的时间点两者相减就是完整的响应时间里面包含请求帧发完后的一部分、t3.5、从站处理时延和 RS485 方向切换时间。如果再用示波器配合 485 差分探头看能把这些时间段拆得更细。3.3 RS485 半双工方向切换常规可以忽略但不要太绝对RS485 是半双工总线同一时刻只能有一个方向在发送。主站发完请求后要切换到接收模式从站发完响应后也要切回接收模式。方向切换的耗时要看具体硬件方案。采用 MAX485 这类收发器配合 MCU 的 RTS 引脚控制时切换时间通常是几十微秒到一两百微秒远小于 9600 波特率下的 t3.53.65ms基本可以忽略。但如果使用了带隔离的 485 模块、光耦隔离的自动收发电路或者一些慢速的软件控制切换切换时间有可能达到毫秒级。这时如果切换时间接近甚至超过 t3.5就需要把它单独计入总时间链否则实测周期会比理论值多出一截。另外说一句现在很多 USB 转 485 模块用自动收发电路内部会检测串口发送结束并自动切换方向。这类模块在切换瞬间需要在线上产生一个短暂的空闲电平有些质量差的模块切换过程会产生毛刺影响下一帧的接收。挑选模块时尽量选带隔离、方向切换干脆的品牌不要在这个地方省钱。3.4 完整时间链公式从请求首字节到响应末字节把上面几段拼起来单次轮询周期可以由下式表达T_cycle 请求帧耗时 T3.5 从站处理时延 方向切换时间 响应帧耗时 T3.5如果方向切换时间很小可以并入从站处理时延或者 t3.5 里公式变成T_cycle ≈ 请求帧耗时 响应帧耗时 2 × T3.5 从站处理时延用一个实际例子走一遍主站读取一台电表的 10 个保持寄存器波特率 96008N1从站处理时延假设 5ms。请求帧 8 字节8 × 1.0417 8.33ms响应帧 25 字节25 × 1.0417 26.04mst3.53.65ms出现两次从站处理时延5ms总周期 8.33 26.04 3.65 × 2 5 46.67ms。如果按这个周期连续轮询理论最大轮询频率大约是 21 次/秒。如果实际项目要求每秒刷新 50 次那就需要提高波特率或者减少单次读取的寄存器数量。4. 从单站到 32 站轮询周期怎么估算4.1 单台设备的“一次读取全流程”把单站算清楚后多站轮询就只是乘法了但有一个前提Modbus RTU 是主从式协议从站不能主动上报数据只能由主站逐个查询。这意味着总线上的总耗时几乎等于所有从站单次轮询时间的累加。为了保证数据刷新及时工程里通常的做法是每台设备每次只读自己真正需要的寄存器而不是抱着“反正一次能读 125 个干脆全读回来”的心态。读的寄存器越多响应帧越长单站耗时越长牺牲的是整个网络的刷新率。比如某台设备只需电流、电压、功率这三个量那就是 3 个寄存器响应帧 11 字节如果你把它的所有 50 个寄存器都读回来响应帧就是 105 字节耗时翻了近 10 倍但绝大多数数据用不上。判断一次读多少个才合理可以反过来算先确定允许的单站时间预算再推算最大可读寄存器数。比如要求单站轮询不超过 40ms9600 波特率下请求和帧间隔已经占掉 15.6ms剩下约 24ms 给响应和从站处理。响应帧每多读一个寄存器多 2.08ms从站处理按 5ms 算那么最多读约 8 个寄存器。4.2 32 台设备的轮询时间对比拿热搜里经常提到的“32 台变频器通过 Modbus 通讯”来说假设每台变频器读取 4 个寄存器从站处理时延保守取 10ms波特率分别取 9600、19200、1152008N1计算单站周期9600请求 8 字节 8.33ms响应 13 字节 13.54mst3.5 两次 7.29ms从站处理 10ms合计约 39.2ms32 台约 1.25s。19200请求 4.17ms响应 6.77mst3.5 两次 3.65ms从站处理 10ms合计约 24.6ms32 台约 0.79s。115200请求 0.69ms响应 1.13mst3.5 两次 0.61ms从站处理 10ms合计约 12.4ms32 台约 0.40s。注意一个很有意思的规律从 9600 升到 19200波特率翻倍但总周期只从 1.25s 降到 0.79s没有减半。原因是从站处理时延 10ms 占了很大比重波特率再提高也压不掉这部分。实际项目里如果从站处理很慢提高波特率的收益会被明显稀释这时更应该考虑的是把从站功能码处理逻辑优化好或者减少每次读取的寄存器个数。如果从站处理时延只有 2ms同样 32 台设备9600 下约 1.0s115200 下约 0.14s差距就非常明显了。所以做理论计算时从站处理时延这个参数一定不能拍脑袋取值不同结论可能完全不同。4.3 Modbus Poll 里的超时参数怎么填很多人用 Modbus Poll 调设备卡在“Response Timeout”和“Delay Between Polls”这两个参数上。默认值往往不适合你的现场需要按理论计算来设置。Response Timeout 是从主站发出请求后开始计时到收到响应帧的等待上限。这个值必须大于“请求帧耗时 t3.5 从站处理时延 响应帧耗时”。还是用上面电表的例子理论值是 46.67ms那超时至少设成 100ms留一倍余量。如果设得比理论值还小从站只是稍微慢一点主站就判超时并重发反而增加总线负担。Delay Between Polls 是相邻两轮请求之间的额外间隔。Modbus 协议只要求帧间有 t3.5 静默但很多情况下主站在响应完成后立刻发下一帧。如果从站对连续请求处理不过来可以在这个参数里加 10~50ms。对于老旧设备建议查手册看有没有“帧间最小间隔”的要求这个参数往往比协议规定的 t3.5 更长。轮询间隔不是越小越好。总线上一旦发生超时重发重发占用的时间会让后续所有从站的刷新周期进一步恶化形成雪崩效应。宁可把轮询周期放宽一点也要保证每一轮都不出错。4.4 可复用计算步骤三分钟算出整个网络周期把前面所有内容压缩成一套可以直接套用的步骤确认从站串口格式8N1 还是 8E1/8N2得到单字节 bit 数。计算 TB bit 数 / 波特率。摸清从站处理时延现场实测或查手册实在拿不到值先用 10ms 作为初始假设。确定每台从站本次要读的寄存器数 N计算请求帧耗时 8 × TB响应帧耗时 (5 2N) × TB。单站周期 请求帧耗时 响应帧耗时 2 × 3.5 × TB 从站处理时延。网络总周期约等于所有从站单站周期之和再留 20%~50% 的运行余量。这套流程在 9600 到 115200 波特率范围内都适用。只要输入参数没搞错算出来的周期和实际跑出来的结果一般不会差太多。5. 理论值和实测对不上时的排查思路5.1 主站软件和 USB 转 485 适配器的隐性开销理论计算默认的是“UART 数据一旦准备好就立刻发到线上”但实际主站设备的软件栈会引入额外延迟。比如 PC 上的 Modbus 调试软件通过 USB 转 485 模块发数据USB 的枚举周期是 1ms 或者 125μs数据从应用层到串口芯片、再到差分线中间会有调度延迟。波特率越高这部分延迟对总周期的影响越明显。PLC 做 Modbus 主站时扫描周期和通讯任务往往不在同一个优先级上。有些 PLC 的程序扫描周期是 10ms串口通讯在后台执行那么无论理论计算多精确实测响应时间都会被 PLC 的程序周期拉长。遇到这类情况最好在 PLC 程序里读取系统提供的通讯状态时间戳而不是拿秒表按。5.2 从站处理时延不是恒定值理论计算通常把从站处理时延当作常数但实际设备里这个值是波动的。单片机从站如果在响应处理期间来了一次定时器中断或者 RTOS 里高优先级任务抢占从站响应就会慢一截。有些变频器的 Modbus 处理在后台循环里负载越重响应越慢峰值和平均值可能差好几倍。所以理论计算给出的只是一个中位值。设置超时和轮询周期时要用从站的“最坏情况处理时延”而不是平均值。如果你用示波器看到多次请求中从站响应时间忽大忽小变化幅度超过理论周期的 20%那就说明从站任务调度不稳定宜把轮询间隔再放大。5.3 帧内字节间隔超标导致丢帧重发前面提到Modbus RTU 要求帧内两个字节的间隔不超过 1.5 个字符时间否则从站判定帧不完整并丢弃。很多丢帧问题就出在这里。主站发送请求时如果 UART 发送 FIFO 深度不够又恰好在发送过程中被高优先级中断打断两个字节之间就可能被拉开很长的间隔。比如 9600 波特率下 1.5 个字符时间约 1.56ms普通单片机在发送 8 字节时稍微处理一下别的事情间隔就可能超标。从站丢帧后不回复主站等超时重发白白浪费一个轮询周期。排查这类问题用逻辑分析仪抓 RS485 线上的波形或者用支持 RS485 的示波器探头看帧内字节间隔能直接判断。Modbus 调试软件里显示“请求发出但无响应”的次数变多时也可以先怀疑主站帧间隔超标而不是怀疑从站没收到。5.4 线路长度和隔离器件引入的边沿延迟RS485 标准规定总线理论最大长度 1200 米信号在双绞线上的传播速度大约是每微秒 200 米单程 1200 米约 6 微秒。这个延迟和毫秒级运算相比可以忽略不计真正需要担心的是线路过长导致信号边沿变缓接收端要把一个 bit 的采样点放在稳定区间里如果边沿太缓采样点就会飘。这通常不直接影响总耗时但会导致误码重发从而让实际平均周期变长。加了光电隔离的 485 模块数字侧到总线侧会有几微秒到几十微秒的传播延迟个别光耦老化后导通延迟还会增加。这类延迟在低速时无所谓但在 115200 波特率下一个 bit 才 8.68 微秒如果光耦延迟达到 2~3 微秒再加上线路反射收发双方的采样点余量就会被吃掉不少。5.5 实测手段时间戳和示波器是最后裁判理论算得再漂亮最终也要回到实测。我的习惯做法是分三步走先用 Modbus Poll 跑连续轮询对比它的“平均循环时间”和理论计算值差距在 10% 内属于正常。再用逻辑分析仪或示波器抓一个完整请求-响应过程把每一段请求帧、帧间隔、从站处理、响应帧的时间量出来和理论计算的各段逐一对照。最后把 Response Timeout 从理论值起步逐级下调观察什么时候开始出现超时重发那个临界点往往能暴露出后一问题。我自己调过一条挂了 24 台仪表的 485 总线理论计算的轮询周期是 780ms实测稳定在 810ms 左右差距很小。但把波特率从 9600 提升到 19200 后理论值掉到 410ms实测却只有 580ms多出来的时间就是几台从站设备的响应延迟不稳定。后来给这几台设备单独加了 20ms 的轮询间隔整个网络就安静了。这类问题光看协议层很难发现一定要回到时间轴上去找。RS485 上的 Modbus RTU 从来不是一个“发出去就完事”的协议它的每一次读写都是比特、字节、帧间隔和设备处理时间共同作用的结果。把读寄存器的耗时算清楚你在现场调参数时就不是瞎猜而是手里拿着一张准确的时间预算表。