RS-485 与 Modbus:差分总线上的一主多从轮询
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」**入门层(beginner)**数字逻辑基础第一百零四篇。UART只会点对点、对地电平、几米就不行;工厂里传感器、变频器、PLC 之间动辄几百米、强电磁干扰,于是把同样的异步字节放到 RS-485 差分线上,再用 Modbus RTU 规定「谁先说、说什么」。它和 CAN是工业现场最常见的两条总线。
本文要回答的问题
- RS-485 的 A/B 差分为什么比 TTL/RS-232 传得远、抗干扰?
- 半双工总线上的 DE/RE 方向切换什么时候做,做早做晚会怎样?
- Modbus RTU 一帧由哪几部分组成?功能码 03/06/10 在读写什么?
- 多个从机靠什么区分?为什么 RS-485 自己不仲裁、只能主站轮询?
- 帧与帧之间怎么分界?Modbus CRC16 有什么特别?
一、RS-485 物理层:平衡差分、半双工
RS-485(EIA-485)是电气规范,数据格式仍是普通 UART 的 8N1/8E1:
- 平衡差分:用一对线 **A(D−)/B(D+)**的电压差表示 1/0(通常 B>A 为 1,约定依器件标注),共模噪声在两线上等幅出现、被接收端相减抵消,故能传 1200 米、抗强干扰;
- 半双工总线:所有节点的 A 接 A、B 接 B 并联,任一时刻只能一个发送;总线两端各并 120Ω 终端电阻匹配线缆;
- 节点数:按「单位负载」计,标准收发器驱动 32 个单位负载(1/8 UL 器件可挂更多);
- 失效偏置(failsafe bias):总线空闲无人驱动时压差为 0 处于不确定,靠偏置电阻或带 failsafe 的接收器把空闲确定为逻辑 1(标记态),避免误起始位。
二、方向控制:DE/RE 与时序
收发器有使能脚:DE 打开发送驱动器、/RE 打开接收器(常把 DE 和 /RE 接在一起由一个 GPIO 控制)。发送前置 1(发送)、发完立刻置 0(接收)。切换时机是关键坑:
- 太早切接收:最后一个停止位还没真正驱动到线上就被截断,从机收不到完整字节;
- 太晚切回:主机仍占着总线,从机的应答被顶回去或撞车;
- 正确做法是在最后一个停止位的最后一位移出后(用 UART 的 TC/TXE「发送完成」中断,而非写入发送寄存器就切)再拉低 DE,给收发器和总线留 1 个位时间左右余量。
RS-485 只定义电气,本身没有仲裁、没有地址、没有应答规则——谁能说话、说什么由上层协议规定,最常见就是 Modbus。
三、Modbus RTU:一主多从、请求-应答
Modbus 把设备建模成一组寄存器:线圈(1 位)和寄存器(16 位),又分只读输入和可读写保持寄存器。RTU 帧结构:
[从机地址 1B][功能码 1B][数据 nB][CRC16 2B,低字节先发]- 地址:每个从站 1~247 唯一;主站请求里带目标地址,只有它应答;地址 0 为广播(写命令、无从站应答);
- 常用功能码:0x03 读保持寄存器、0x04 读输入寄存器、0x01 读线圈、0x06 写单个保持寄存器、0x10 写多个保持寄存器;
- 读请求数据段=起始寄存器号(2B)+数量(2B);从站回=字节数+寄存器值;写请求直接带值;
- 因为没有片选线,地址字段就是「这帧给谁」的选择机制。
主站严格轮询:发一帧→等对应从站应答(超时则重发/报错)→再问下一个。从站绝不能主动发话,因此不会冲突——用「主从调度」代替了 CAN的硬件仲裁,简单但实时性取决于轮询周期。
四、帧间隔与 CRC16
- 帧边界靠静默:RTU 模式没有起始符,规定两帧之间总线空闲 ≥3.5 个字符时间(9600bps 下约 4ms),同一帧内字节间隔不得超过 1.5 字符,接收方靠「3.5 字符空闲」判定一帧结束。这要求 UART 接收用空闲中断或定时器来组帧,不能只按字节读;
- CRC16-Modbus:多项式 0xA001(即 0x8005 反射),初值 0xFFFF,结果低字节在前发送;和一般 CRC 字节序相反,移植常见错误就在初值/字节序(CRC 原理见 CRC/LFSR);
- 异常时从站回功能码最高位置 1(如 0x83)+ 异常码(非法地址/数据等)。
五、变体与对比
- Modbus ASCII:用可见 ASCII、冒号
:开头、回车换行结束、LRC 校验,效率低但可读性好; - Modbus TCP:跑在以太网上,用 MBAP 头(事务号/协议/长度/单元号)代替地址和 CRC(TCP/IP 已保证校验),端口 502;
- RS-485 差分+Modbus 主从适合「几百米、几十节点、周期采集」的 PLC/变频器/仪表网络;需要多主、优先级和硬件错误隔离时用 CAN,需要大带宽用以太网。
与现有篇目的衔接
总结
一句话总结:RS-485 把普通 UART 字节搬到平衡差分物理层上,用 A/B 两线电压差表示 1/0,使共模干扰被相减抵消,从而支持约 1200 米传输和数十到数百个按单位负载计的节点,总线半双工、所有节点同名线并联、两端各接 120Ω 终端电阻,并靠失效偏置把空闲确定为标记态;收发器用 DE//RE 切换收发方向,必须在最后一个停止位真正移出(TC 发送完成)后再切回接收,过早会截断停止位、过晚会顶住从机应答。RS-485 只规定电气、不含仲裁和地址,上层最常用 Modbus RTU 做一主多从请求-应答:帧为从机地址、功能码、数据、CRC16,从站靠地址字段被选中(0 为广播),0x03/0x04 读寄存器或输入、0x06/0x10 写单个或多个保持寄存器,主站逐个轮询、从站绝不主动发话,用调度避免冲突,实时性取决于轮询周期;帧之间靠至少 3.5 个字符时间的总线静默分界,校验用初值 0xFFFF、多项式 0xA001 且低字节先发的 CRC16-Modbus,异常应答把功能码最高位置 1。它另有 ASCII 和基于以太网 MBAP 头、端口 502 的 Modbus TCP 变体,适合长距离多节点周期采集,与带硬件仲裁的 CAN 和高带宽以太网互补。