现场布了一根 485 线,短距离试的时候通得好好的,拉到几十米一挂设备,帧开始丢,再长直接全错。还有一回,两个配电柜之间的 485 一上电,收发器冒烟,查下来是两地电位差几百伏,把芯片打穿了。
RS485 看起来就是「两根线跑串口」,比 CAN 简单,但真上线最容易出幺蛾子的就是它。问题几乎都出在差分、终端、方向控制和隔离这四件事上。这篇把工程里最常踩的点摊开讲,不绑任何芯片。
差分信号才是它抗干扰的根本
RS485 用的是两根线 A、B 的差分电压来判断逻辑,不是看对地电压。发送端让 A 比 B 高过 200mV 表示 1(Mark),B 比 A 高过 200mV 表示 0(Space)。接收端只关心 VA - VB,共模范围能到 -7V 到 +12V。
这一点是它比 RS232 耐造的原因:现场干扰往往是共模的(两条线同时被抬升或叠加噪声),差分接收把这部分抵消掉了。所以走线要扭成双绞线,让两根线尽量对称地耦合同一干扰,接收端才好抵消。
半双工:方向得自己管
最常见的 485 芯片(像 MAX485、SP3485)是两线半双工。同一对 A/B 线,要么发要么收,不能同时进行。收发切换靠两个脚:DE(驱动使能,发)和 RE(接收使能,收,低有效)。实际板子常把 DE 和 RE 反相接到同一个 GPIO,一个脚控方向。
发送前拉高 DE,发完必须等最后一个字节真正从移位寄存器移出去再拉回接收,否则最后那个字节会被自己截断。
c
void rs485_send(uint8_t *buf, uint16_t len)
{
HAL_GPIO_WritePin(DE_PORT, DE_PIN, GPIO_PIN_SET); // 切到发送
HAL_UART_Transmit(&huart3, buf, len, HAL_MAX_DELAY);
// 关键:等发送移位寄存器空(含停止位)再切回接收
while (!__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TC))
;
HAL_GPIO_WritePin(DE_PORT, DE_PIN, GPIO_PIN_RESET); // 切回接收
}
很多人用 DMA 发送,发完进的是 DMA 完成中断,但这时字节还在 UART 移位寄存器里没完全发出去,要在 UART 的发送完成(TC)中断里再切方向,不能 DMA 完成就切。
终端电阻:只在两端加,全程都加反而错
信号在电缆里是以波的形式传的。电缆有特性阻抗,双绞线 485 典型是 120Ω。如果末端不接匹配的电阻,信号走到头会反射回来,和原信号叠加,在波形上形成过冲和振铃,误码就来了。

标准做法:在总线的最远两端各并一个 120Ω 电阻,匹配特性阻抗。中间的节点一律不加。如果所有节点都加,并联电阻太多,终端等效阻抗被拉低,驱动能力不够,电平又垮了。
短距离(一两米)、低速时可以省掉终端电阻,但上了几十米或高波特率,两端 120Ω 是必须的。
空闲时的电平:偏置电阻不能少
总线所有节点都不发的时候,A/B 是悬空的,差分电压接近 0,落在接收器的不确定区(±200mV 以内),接收端可能乱翻。标准做法是在主机端给 A 上拉、B 下拉,让空闲时 A 略高于 B,明确成 Mark 态(逻辑 1)。这就是失效保护偏置电阻,通常 680Ω 到 1kΩ 量级配合终端电阻用。

隔离:地电位差比干扰更致命
多个 485 节点如果分布在不同配电柜,地的电位可能差出几十甚至几百伏。这时候 A/B 线上的共模直接超了芯片承受范围,轻则乱码,重则烧片。解决办法是信号和电源都隔离:用数字隔离器(或高速光耦)隔开 A/B 侧的逻辑,用隔离电源(DC-DC 隔离模块或带变压器的收发器)给远端收发器供电,两端不共地。
不隔离又共地,等于把两地用一根线短接,地电位差全加在接口上,迟早出事。
10 个容易踩的坑
- 只在主机端加了终端电阻,从机端没加,长距离反射严重,帧漏一半。
- 每个节点都并 120Ω,并联太多把总线阻抗拉垮,高电平出不来。
- 方向切换太早,DMA 完成就切接收,最后一个字节被自己截断,对端永远收不全。
- 忘了偏置电阻,总线空闲时电平在不确定区,接收端疯狂吐乱数。
- 多柜之间共地不隔离,地电位差几百伏,一上电收发器烧毁。
- 波特率按芯片上限设,不顾线长和电容,距离一长上升沿被电缆电容拖平,采样点采到斜坡。
- 节点数超了收发器负载能力(单位负载 1/8 才支持多节点),挂多了总线驱动不动。
- A、B 接反,整条总线不通,还以为是程序问题,查半天。
- 双绞线没扭、和动力线并行敷设,共模干扰进不来抵消,误码率飙升。
- 热插拔节点没考虑上电瞬态,带电插拔把总线瞬时短路,连累其他节点。
配套骨架:一条稳妥的 485 链路
1. 双绞线敷设,A/B 严格绞合,远离动力线
2. 总线最远两端各并 120Ω 终端电阻
3. 主机端 A 上拉、B 下拉(偏置电阻)保证空闲为 Mark
4. 跨配电柜必做信号+电源隔离,两端不共地
5. MCU 侧一个 GPIO 控 DE/RE 方向,发送完等 TC 再切接收
6. DMA 发送时,方向回切放在 UART 的 TC 中断里,不在 DMA 完成里
7. 波特率按线长降额,长距离别硬上最高速
485 的可靠性不靠协议,靠物理层。差分、终端、偏置、隔离、方向时序,这五件事有一件没做对,上层协议再漂亮也白搭。
下一篇聊另一类「写进去的东西怎么不掉」的问题:EEPROM/Flash 的磨损均衡和掉电保护。