2. UART基础回顾:异步串行通信原理、帧格式、波特率与电平标准

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是嵌入式系统中最基础、最常用的串行通信接口之一。在深入多串口扩展方案之前,必须牢固掌握UART的核心原理。本节将从异步通信机制、数据帧结构、波特率配置以及电平标准四个维度进行系统回顾。

2.1 异步串行通信原理

UART采用异步方式传输数据,这意味着收发双方不需要共享同一时钟信号。取而代之的是,双方通过预先约定相同的波特率来同步数据采样时刻。通信链路中仅需两根信号线:TX(发送)和RX(接收),数据以串行方式逐位在单根线上传输。

核心特点:
  • 无时钟线:节省引脚资源,适合远距离或引脚受限场景。
  • 全双工:TX和RX独立,可同时发送和接收。
  • 起始位同步:每次传输以起始位下降沿作为帧同步标志。

下图展示了UART异步通信的基本链路模型:

UART 异步通信链路模型 发送端 (TX) MCU / 外设 接收端 (RX) MCU / 外设 TX → RX RX → TX ⚠ 异步通信关键约束 收发双方必须配置相同的波特率、数据位、停止位和校验方式,否则数据解析将出错。

2.2 UART帧格式

UART数据以帧为单位进行传输。一个标准的数据帧由以下字段按顺序组成:

字段 位宽 电平状态 说明
空闲位 无限制 高电平 (逻辑1) 总线空闲时保持高电平,标识线路可用。
起始位 1 bit 低电平 (逻辑0) 下降沿标志帧开始,接收端以此同步采样时钟。
数据位 5 ~ 9 bits LSB 优先 实际有效数据,常用 8 bits(1字节)。
校验位 0 / 1 bit 奇/偶/无 可选,用于简单检错。
停止位 1 / 1.5 / 2 bits 高电平 (逻辑1) 帧结束标志,提供帧间间隔。

下图以 8N1(8数据位、无校验、1停止位)格式为例,展示一帧数据的完整波形:

UART 帧格式示例:8N1(数据 0x55 = 01010101b) 空闲 起始 D0=1 D1=0 D2=1 D3=0 D4=1 D5=0 D6=1 D7=0 停止 间隔 起始位 数据位 停止位
常见帧格式速查:
  • 8N1:8数据位 + 无校验 + 1停止位(最常用,兼容性好)
  • 8E1:8数据位 + 偶校验 + 1停止位
  • 8O1:8数据位 + 奇校验 + 1停止位
  • 9N1:9数据位 + 无校验 + 1停止位(用于多机通信地址/数据标志)

2.3 波特率

波特率(Baud Rate)定义每秒传输的符号数。在UART中,一个符号对应一个比特位,因此波特率等于比特率(bps)。波特率决定了每一位的持续时间:

位时间 (Tbit) = 1 / 波特率

例如,波特率 115200 bps 时,每位持续约 8.68 µs。收发双方必须使用相同的波特率,且允许存在一定误差(通常要求 < ±2%)。

波特率 (bps) 位时间 传输1字节耗时 (8N1) 典型应用场景
9600 104.17 µs ≈ 1.04 ms 调试终端、低速传感器
38400 26.04 µs ≈ 260 µs GPS模块、工业仪表
115200 8.68 µs ≈ 86.8 µs 蓝牙模块、Wi-Fi模块、标准调试
921600 1.09 µs ≈ 10.9 µs 高速数据采集、FPGA通信
波特率误差陷阱:当MCU系统时钟无法精确分频出目标波特率时,会产生累积误差。例如,使用16MHz晶振在115200波特率下,若分频器取整误差超过2%,长帧传输(如连续发送多字节)可能导致采样点偏移到错误位。建议优先选择系统时钟可整除的波特率,或使用带小数分频的UART外设。

2.4 电平标准

UART定义的是逻辑协议,物理层电平标准由具体接口规范决定。嵌入式开发中最常见的两种电平标准对比如下:

特性 TTL / CMOS 电平 RS-232 电平
逻辑1 VCC (通常 3.3V 或 5V) -3V ~ -15V
逻辑0 GND (0V) +3V ~ +15V
电压摆幅 小 (0 ~ 3.3V/5V) 大 (±12V 典型)
抗干扰能力 弱 强(适合长距离)
典型距离 < 1.5 米 可达 15 米
接口芯片 MCU 直接输出 需 MAX232 / SP3232 等电平转换

下图展示了TTL与RS-232电平在相同数据帧下的波形差异:

TTL vs RS-232 电平标准对比(同一帧数据) TTL (3.3V) 3.3V 0V RS-232 (±12V) -12V +12V 注意:RS-232 逻辑电平与 TTL 相反(负逻辑),且电压摆幅更大,不能直接连接 MCU 引脚。 必须使用 MAX232 等电平转换芯片进行双向转换。

2.5 嵌入式开发中的UART配置实践

在STM32、ESP32等主流MCU上初始化UART时,通常需要配置以下参数。以下是一个典型的初始化代码示例:

// STM32 HAL 库 UART 初始化示例
UART_HandleTypeDef huart1;

void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;          // 波特率
    huart1.Init.WordLength = UART_WORDLENGTH_8B;  // 8 数据位
    huart1.Init.StopBits = UART_STOPBITS_1;       // 1 停止位
    huart1.Init.Parity = UART_PARITY_NONE;         // 无校验
    huart1.Init.Mode = UART_MODE_TX_RX;           // 全双工
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;  // 无硬件流控
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;

    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        Error_Handler();
    }
}
配置要点总结:
  1. 波特率:与对端设备严格一致,优先使用标准值(9600/115200/921600)。
  2. 数据位:绝大多数场景使用8位,对应1字节数据。
  3. 停止位:1位最常用;2位用于噪声环境或低速设备。
  4. 校验位:无校验(N)兼容性最好;偶校验(E)用于工业总线;奇校验(O)较少见。
  5. 硬件流控:RTS/CTS可防止接收缓冲区溢出,但会增加引脚占用。