返回博客
RS-485 总线设计避坑指南:终端电阻、偏置电阻与多节点挂载

RS-485 总线设计避坑指南:终端电阻、偏置电阻与多节点挂载

RS-485 电气特性

RS-485(TIA/EIA-485)是平衡差分传输标准,使用 A(非反相)和 B(反相)两根信号线传输数据。差分信号通过电压差表示逻辑状态,抗共模干扰能力强。

逻辑电平定义:

  • 逻辑 1:A 比 B 高 200mV 以上(VA - VB > +200mV)
  • 逻辑 0:B 比 A 高 200mV 以上(VB - VA > +200mV)
  • 不确定区:|VA - VB| < 200mV

共模电压范围:-7V 至 +12V。收发器必须在此范围内正常工作,超出范围可能导致器件损坏或通讯失败。

MAX485 收发器原理

MAX485 是半双工 RS-485 收发器,典型电路包含 RO(Receiver Output)、DI(Driver Input)、DE(Driver Enable)、RE(Receiver Enable)、A、B 六个引脚。

    MCU          MAX485         RS-485总线
  +-----+      +---------+      +-------+
  |  TX | ---> |   DI     |      |       |
  |     |      |          |      |       |
  |  RX | <--- |   RO     |      |       |
  |     |      |          |      |       |
  | GPIO| ---> |   DE     | ---> |   A   |---+
  |     |      |          |      |       |   |
  | GPIO| ---> |   RE     |      |   B   |---+
  +-----+      +---------+      +-------+

DE(Driver Enable)和 RE(Receiver Enable)控制收发方向:

  • DE = 1、RE = 0:发送模式,DI 数据驱动到 A/B 线
  • DE = 0、RE = 1:接收模式,A/B 线数据从 RO 输出

通常将 DE 和 RE 连接在一起,由 MCU 单个 GPIO 控制。高电平发送,低电平接收。

STM32 控制 MAX485 的代码示例:

#include "stm32f1xx_hal.h"

#define RS485_DE_RE_PIN GPIO_PIN_1
#define RS485_DE_RE_PORT GPIOA

void RS485_Set_Mode_TX(void) {
    HAL_GPIO_WritePin(RS485_DE_RE_PORT, RS485_DE_RE_PIN, GPIO_PIN_SET);
    HAL_Delay(1);  // 等待收发器切换
}

void RS485_Set_Mode_RX(void) {
    HAL_GPIO_WritePin(RS485_DE_RE_PORT, RS485_DE_RE_PIN, GPIO_PIN_RESET);
    HAL_Delay(1);  // 等待收发器切换
}

// 发送数据
void RS485_Send_Data(uint8_t *data, uint16_t len) {
    RS485_Set_Mode_TX();
    HAL_UART_Transmit(&huart1, data, len, 1000);
    RS485_Set_Mode_RX();
}

终端电阻

RS-485 总线特性阻抗约为 120Ω,传输线末端需并联 120Ω 终端电阻以消除信号反射。反射会导致波形畸变、误码率上升。

终端电阻安装位置:

  • 总线两端各接一个 120Ω 电阻(A-B 之间)
  • 短距离(<10米)可省略
  • 长距离(>100米)必须安装

典型总线拓扑:

主机    节点1    节点2    节点3    节点4
  |       |       |       |       |
  +---+---+---+---+---+---+---+---+
      |               |
     120Ω           120Ω

终端电阻计算:

// 终端电阻功耗计算
#define RS485_TERMINAL_RESISTANCE 120.0f
#define RS485_DRIVER_VOLTAGE 5.0f

float terminal_power = (RS485_DRIVER_VOLTAGE * RS485_DRIVER_VOLTAGE) / 
                       RS485_TERMINAL_RESISTANCE;
// 结果约 0.208W,选用 1/4W 或 1/2W 电阻

空闲态偏置电阻

RS-485 总线空闲时,所有节点处于接收模式,总线处于高阻态。此时 A/B 线电压差可能小于 200mV,导致接收器输出不确定状态,引发误判。

偏置电阻解决此问题:在 A 线接上拉电阻到 VCC,B 线接下拉电阻到 GND,确保空闲时 A > B。

偏置电阻计算:

// 假设总线上有 N 个节点,每个节点输入阻抗 12kΩ(标准值)
#define NODE_COUNT 10
#define NODE_INPUT_IMPEDANCE 12000.0f
#define VCC 5.0f
#define TARGET_IDLE_DIFF 0.3f  // 目标空闲差分电压 300mV

// 总输入阻抗
float total_input_impedance = NODE_INPUT_IMPEDANCE / NODE_COUNT;  // 1200Ω

// 偏置电阻选择(经验值)
#define BIAS_RESISTANCE_UP 560.0f    // A 线上拉
#define BIAS_RESISTANCE_DOWN 560.0f  // B 线下拉

// 验证空闲差分电压
float va_idle = VCC * (total_input_impedance / (BIAS_RESISTANCE_UP + total_input_impedance));
float vb_idle = VCC * (total_input_impedance / (BIAS_RESISTANCE_DOWN + total_input_impedance));
float diff_idle = va_idle - vb_idle;  // 应大于 200mV

常用偏置电阻组合:

  • 560Ω / 560Ω:适用于 10-20 个节点
  • 1kΩ / 1kΩ:适用于 5-10 个节点
  • 2.2kΩ / 2.2kΩ:适用于 <5 个节点

偏置电阻仅在总线一端安装,通常在主机侧。

多节点负载能力

RS-485 标准定义单位负载(Unit Load)为 12kΩ 输入阻抗。标准收发器为 1 单位负载,最多支持 32 个节点(32 × 12kΩ = 375Ω ≥ 最小负载阻抗)。

低功耗收发器(1/4 单位负载、1/8 单位负载)可扩展节点数:

  • 1/4 单位负载(48kΩ):最多 128 个节点
  • 1/8 单位负载(96kΩ):最多 256 个节点

节点数计算:

#define UNIT_LOAD_IMPEDANCE 12000.0f
#define MIN_BUS_IMPEDANCE 375.0f

// 标准收发器最大节点数
uint16_t max_nodes_standard = UNIT_LOAD_IMPEDANCE / MIN_BUS_IMPEDANCE;  // 32

// 1/4 单位负载收发器最大节点数
uint16_t max_nodes_quarter = (UNIT_LOAD_IMPEDANCE * 4) / MIN_BUS_IMPEDANCE;  // 128

实际应用中建议预留 20% 余量,32 节点总线建议挂载不超过 25 个节点。

布线长度与波特率关系

RS-485 通讯距离受波特率限制,波特率越高,允许距离越短。理论关系:

最大距离(m) = 100000 / 波特率(bps)

实际应用参考:

波特率最大距离推荐距离
96001200m1000m
19200600m500m
38400300m250m
57600200m150m
115200100m80m

长距离通讯需注意:

  • 使用屏蔽双绞线(推荐 22AWG 或 24AWG)
  • 屏蔽层单端接地(通常在主机侧)
  • 避免与强电线路平行布线
  • 总线拓扑为菊花链,避免星形连接

常见故障排查

波形畸变

现象:示波器观察 A/B 线波形,上升/下降沿缓慢、有过冲或振铃。

原因:

  • 终端电阻未安装或阻值错误
  • 总线过长,特征阻抗不匹配
  • 分布电容过大(线缆过长、节点过多)

解决:

  • 检查并安装 120Ω 终端电阻
  • 缩短总线长度或降低波特率
  • 减少节点数或使用低电容收发器

通讯丢包

现象:主站轮询从站,偶尔无响应或 CRC 错误。

原因:

  • 总线空闲态偏置电阻缺失
  • 接地不良,共模干扰
  • 波特率不匹配
  • 终端电阻功率不足,发热导致阻值变化

排查步骤:

// 1. 检查空闲态电压差
float measure_voltage_diff(void) {
    float va = ADC_Read_Channel(A_CHANNEL);
    float vb = ADC_Read_Channel(B_CHANNEL);
    return va - vb;  // 应大于 200mV
}

// 2. 检查终端电阻
float check_termination_resistance(void) {
    // 断电状态下测量 A-B 之间电阻
    return Measure_Resistance(A_PIN, B_PIN);  // 应接近 120Ω
}

// 3. 验证波特率
void verify_baudrate(void) {
    // 使用示波器测量位宽
    // 位宽(μs) = 1000000 / 波特率
    // 19200 波特率位宽应为 52.08μs
}

共地干扰

现象:通讯正常但偶尔出现大量错误码,设备地之间存在电位差。

原因:不同设备地电位不等,形成地环路电流。

解决:

  • 使用光电隔离(光耦或数字隔离芯片)
  • 屏蔽层单端接地
  • 共模扼流圈抑制共模噪声

DE/RE 切换时序问题

现象:发送数据后立即切换到接收模式,导致最后一个字节丢失。

原因:收发器切换时间约 1-2μs,切换过快导致数据未完全输出。

解决:

void RS485_Send_Data_Fixed(uint8_t *data, uint16_t len) {
    RS485_Set_Mode_TX();
    HAL_UART_Transmit(&huart1, data, len, 1000);
    
    // 等待最后一个字节完全发送(根据波特率计算)
    uint32_t bit_time_us = 1000000 / 19200;  // 19200 波特率
    HAL_Delay((bit_time_us * 10) / 1000 + 2);  // 10 位 + 余量
    
    RS485_Set_Mode_RX();
}

完整电路设计

基于 STM32F103 和 MAX485 的完整电路:

         3.3V
          |
         10k
          |
   PA1 ---+--- DE/RE
          |
         10k
          |
         GND

   PA9 --- DI
   PA10 --- RO

   5V --- VCC
   GND --- GND
         GND --- A --- 120Ω --- B
              |
             560Ω --- 5V
              |
             560Ω --- GND

PCB 布局注意事项:

  • A/B 线平行布线,等长等距
  • 终端电阻靠近连接器
  • 去耦电容(0.1μF)靠近 VCC 引脚
  • 避免高速信号线穿过 RS-485 区域

总结

RS-485 总线设计关键点:

  • 长距离必须安装 120Ω 终端电阻
  • 空闲态需偏置电阻确保确定状态
  • 节点数受单位负载限制,超节点数需用低功耗收发器
  • 波特率与通讯距离成反比
  • 布线采用菊花链拓扑,屏蔽层单端接地
  • DE/RE 切换需留足够时序余量

按上述规范设计,可构建稳定可靠的 RS-485 通讯网络。