2. UART硬件架构:发送器(TX)、接收器(RX)、波特率发生器、控制寄存器概览

UART(Universal Asynchronous Receiver/Transmitter)硬件模块是串行通信的物理基础。理解其内部架构——特别是发送器、接收器、波特率发生器以及控制寄存器的协同工作方式——是编写高效、稳定驱动的前提。本章将拆解UART核心单元,并建立它们之间的数据流与配置关系。

2.1 UART硬件模块顶层架构

一个典型的UART IP核(如16550兼容型)由以下四大功能块构成,它们通过内部总线与CPU交互,并通过外部引脚连接物理层(RS-232/485)。

UART硬件顶层架构图 CPU接口总线 (数据/地址/控制) 控制寄存器组 (IER/FCR/LCR/MCR) 波特率发生器 (DLL/DLM) 发送器 (TX) 发送移位寄存器 (TSR) 发送FIFO (THR) 接收器 (RX) 接收移位寄存器 (RSR) 接收FIFO (RBR) TX 引脚 RX 引脚 波特率时钟驱动TX/RX移位速率,控制寄存器配置工作模式 FIFO与移位寄存器协同实现数据缓冲与串并转换

2.2 发送器(TX)与接收器(RX)

发送器和接收器是UART的数据通路核心,它们各自包含一个移位寄存器和一个FIFO缓冲区。驱动开发中,对这两个模块的配置直接影响吞吐量和实时性。

模块 核心组件 功能描述 驱动关注点
发送器 (TX) 发送保持寄存器 (THR)
发送移位寄存器 (TSR)
CPU将数据写入THR(FIFO或单字节);TSR从THR加载数据并按位串行移出至TX引脚。 FIFO空阈值、发送中断触发条件、字符间延迟
接收器 (RX) 接收缓冲寄存器 (RBR)
接收移位寄存器 (RSR)
RX引脚按位接收串行数据,RSR完成串并转换后存入RBR(FIFO或单字节);CPU从RBR读取。 FIFO满阈值、接收超时中断、帧错误/奇偶校验处理

关键概念: 移位寄存器负责串/并转换,FIFO负责缓冲。驱动开发中,FIFO深度和触发阈值决定了中断频率与CPU负载的平衡点。

2.3 波特率发生器

波特率发生器本质上是一个可编程分频器,它从系统时钟(或专用外设时钟)分频产生UART模块的工作时钟。该时钟直接决定TX/RX的位传输速率。

波特率计算公式如下:

波特率 = 时钟频率 / (16 × 分频系数)

其中:
- 时钟频率:UART模块输入时钟(如 1.8432 MHz、24 MHz 等)
- 分频系数:由 DLL(低位)和 DLM(高位)寄存器组成的 16 位值
- 16:过采样因子(标准UART使用16倍过采样)

典型配置示例(时钟频率 1.8432 MHz):

目标波特率 (bps) 分频系数 (DLL/DLM) 实际波特率 (bps) 误差
9600 12 (0x0C) 9600 0%
19200 6 (0x06) 19200 0%
115200 1 (0x01) 115200 0%

驱动开发陷阱: 部分UART控制器在设置波特率前需要先设置DLAB位(Divisor Latch Access Bit),否则写DLL/DLM寄存器无效。忘记设置DLAB是波特率配置失败的常见原因。

2.4 控制寄存器概览

控制寄存器是驱动与硬件交互的接口。下表列出最关键的几个寄存器及其作用:

寄存器名称 缩写 地址偏移 主要功能
线路控制寄存器 LCR +0x03 配置数据位(5-8)、停止位(1/2)、奇偶校验模式、DLAB位
FIFO控制寄存器 FCR +0x02 使能/清除FIFO、设置FIFO触发阈值(1/4/8/14字节)
中断使能寄存器 IER +0x01 使能接收数据可用、发送保持寄存器空、接收线路状态、MODEM状态中断
MODEM控制寄存器 MCR +0x04 控制RTS/DTR等硬件流控信号、环回模式使能
线路状态寄存器 LSR +0x05 只读状态位:数据就绪(DR)、溢出错误(OE)、奇偶错误(PE)、帧错误(FE)、发送器空(TEMT)

2.5 寄存器配置与数据流交互

驱动初始化时,通常按照以下顺序配置UART硬件:

  1. 设置波特率: 置位LCR的DLAB位 → 写DLL/DLM → 清除DLAB位。
  2. 配置数据格式: 写LCR设置数据位、停止位、校验位。
  3. 配置FIFO: 写FCR使能FIFO、设置触发阈值、清除FIFO。
  4. 配置中断: 写IER使能需要的中断类型。
  5. 配置流控(可选): 写MCR设置RTS/DTR或使能自动流控。
UART驱动初始化配置流程 步骤1 设置波特率 步骤2 配置数据格式 步骤3 配置FIFO 步骤4 配置中断 步骤5 配置流控(可选) 步骤3完成后,步骤4/5 可并行或按需配置

2.6 关键寄存器位域详解

以下代码展示了在驱动中配置LCR和FCR的典型操作,注意位域操作的准确性:

/* 配置LCR: 8数据位, 1停止位, 无校验 */
#define LCR_8BIT  0x03  /* 数据位: 11 = 8位 */
#define LCR_1STOP 0x00  /* 停止位: 0 = 1位 */
#define LCR_NOPAR 0x00  /* 无校验 */
#define LCR_DLAB  0x80  /* 除数锁存访问位 */

void uart_set_format(uint32_t base_addr) {
    uint8_t lcr = LCR_8BIT | LCR_1STOP | LCR_NOPAR;
    *(volatile uint8_t *)(base_addr + 0x03) = lcr;
}

/* 配置FCR: 使能FIFO, 清除FIFO, 触发阈值=8字节 */
#define FCR_ENABLE     0x01
#define FCR_CLEAR_RX   0x02
#define FCR_CLEAR_TX   0x04
#define FCR_TRIGGER_8  0x80  /* 触发阈值: 8字节 */

void uart_fifo_config(uint32_t base_addr) {
    uint8_t fcr = FCR_ENABLE | FCR_CLEAR_RX | FCR_CLEAR_TX | FCR_TRIGGER_8;
    *(volatile uint8_t *)(base_addr + 0x02) = fcr;
}

调试建议: 在初始化完成后,读取LSR寄存器验证配置是否生效。LSR的bit5(TEMT)和bit6(TSRE)可以反映发送器状态;bit0(DR)可以验证接收通路是否正常。

通过以上对UART硬件架构的拆解,驱动开发者可以清晰地理解:波特率发生器提供时间基准,控制寄存器定义行为模式,TX/RX模块完成数据搬运。下一层我们将深入FIFO管理策略,探讨如何利用这些硬件特性实现低延迟、高吞吐的驱动设计。