2. UART硬件架构:深入理解控制器内部结构
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是嵌入式系统中历史最悠久、应用最广泛的串行通信接口之一。要编写高效的UART驱动,首先必须透彻理解其硬件架构。本章将深入剖析UART控制器的内部结构,包括发送器、接收器、波特率发生器以及FIFO缓冲区等核心模块。
2.1 UART控制器整体架构
一个典型的UART控制器内部由多个功能模块组成,它们协同工作以实现串行数据的异步收发。下图展示了UART控制器的核心架构。
从上图可以看出,UART控制器通过系统总线接口与CPU连接,内部包含控制寄存器组、波特率发生器、发送器、接收器、FIFO缓冲区以及中断控制器等模块。下面我们将逐一深入分析每个模块的工作原理。
2.2 发送器(TX)
发送器负责将并行数据转换为串行数据,并按照UART协议帧格式逐位发送到TXD引脚上。其核心组件是发送移位寄存器。
2.2.1 发送器工作原理
- 数据加载:CPU将待发送的数据写入发送数据寄存器(THR),数据被送入TX FIFO或直接送入发送移位寄存器。
- 并行转串行:发送移位寄存器在波特率时钟驱动下,将并行数据逐位移出。
- 帧格式封装:在数据位前后自动添加起始位(0)、可选的奇偶校验位和停止位(1)。
- 位发送:每个位在TXD引脚上保持一个波特率时钟周期。
关键点:UART协议规定数据以LSB(最低有效位)优先的方式发送。这意味着数据字节的位0最先出现在TXD引脚上,位7最后出现。驱动开发中,发送中断通常在发送移位寄存器为空时触发,通知CPU可以写入下一个数据。
2.3 接收器(RX)
接收器与发送器相反,它从RXD引脚接收串行数据,将其转换为并行数据,并去除起始位、校验位和停止位,最终将有效数据存入接收数据寄存器(RBR)或RX FIFO中。
2.3.1 接收器工作原理
- 起始位检测:接收器持续采样RXD引脚,检测到高电平到低电平的跳变(起始位)后开始接收。
- 位采样:在每个数据位的中间时刻(通常使用16倍波特率时钟进行过采样)采样RXD电平,确保数据稳定。
- 串行转并行:接收移位寄存器将接收到的串行位流组装成并行数据。
- 帧校验:检查停止位是否为1,以及奇偶校验位是否正确(如果启用)。
- 数据存储:有效数据被送入RX FIFO或接收数据寄存器,等待CPU读取。
常见问题:接收器可能遇到帧错误(停止位不是1)、奇偶校验错误或溢出错误(前一个数据未被读取,新数据已到达)。驱动开发中必须检查错误标志位,并进行相应的错误处理。
2.4 波特率发生器
波特率发生器是UART的“心跳”,它根据输入的系统时钟产生精确的波特率时钟,控制数据位的发送/接收速率。
2.4.1 波特率计算公式
大多数UART控制器使用以下公式计算波特率:
波特率 = 时钟频率 / (16 × 分频系数)
其中:
- 时钟频率:UART模块的输入时钟(如系统时钟或专用时钟)
- 16:过采样因子(大多数UART使用16倍过采样)
- 分频系数:可编程的分频器值(通常为16位寄存器)
2.4.2 常见波特率与分频系数对照表
| 目标波特率 (bps) | 时钟频率 16 MHz | 时钟频率 24 MHz | 时钟频率 50 MHz |
|---|---|---|---|
| 9600 | 104 (0.16% 误差) | 156 (0.16% 误差) | 325 (0.16% 误差) |
| 19200 | 52 (0.16% 误差) | 78 (0.16% 误差) | 162 (0.16% 误差) |
| 115200 | 8 (2.12% 误差) | 13 (0.16% 误差) | 27 (0.08% 误差) |
| 921600 | 1 (8.51% 误差) | 1 (38.7% 误差) | 3 (1.36% 误差) |
工程实践:波特率误差应控制在±2%以内,否则可能导致通信失败。当误差较大时,可以考虑使用小数分频(Fractional Baud Rate Generator)或选择更合适的系统时钟频率。许多现代MCU的UART支持小数波特率发生器,可以精确匹配标准波特率。
2.5 FIFO缓冲区
FIFO(First In First Out,先进先出)缓冲区是UART控制器内部的小型硬件队列,用于缓解CPU与UART之间的速度不匹配问题。
2.5.1 FIFO的作用
- 减少中断频率:CPU可以在FIFO达到触发阈值时才响应中断,而不是每个字节都中断一次。
- 防止数据丢失:在CPU响应中断前,FIFO可以暂存多个接收到的数据字节。
- 提高传输效率:发送FIFO允许CPU一次性写入多个字节,UART自动逐位发送。
2.5.2 FIFO深度与触发阈值
| FIFO类型 | 典型深度 | 常见触发阈值 | 适用场景 |
|---|---|---|---|
| 无FIFO | 1字节 | 不适用 | 低端MCU,简单应用 |
| 16字节FIFO | 16字节 | 1/4/8/14字节 | 通用嵌入式系统 |
| 64字节FIFO | 64字节 | 1/8/16/32/56字节 | 高速通信,多任务系统 |
| 128字节FIFO | 128字节 | 1/16/32/64/112字节 | DMA传输,高吞吐量 |
2.5.3 FIFO操作流程
2.6 关键寄存器总结
UART驱动开发中需要操作的核心寄存器如下表所示:
| 寄存器名称 | 缩写 | 方向 | 功能描述 |
|---|---|---|---|
| 接收数据寄存器 | RBR | 只读 | 读取接收到的数据(从RX FIFO顶部) |
| 发送数据寄存器 | THR | 只写 | 写入待发送的数据(写入TX FIFO尾部) |
| 波特率除数寄存器 | DLL/DLH | 读写 | 设置波特率分频系数(低字节/高字节) |
| 线路控制寄存器 | LCR | 读写 | 配置数据位、停止位、校验位、波特率访问锁 |
| 线路状态寄存器 | LSR | 只读 | 指示发送/接收状态、错误标志 |
| FIFO控制寄存器 | FCR | 只写 | 使能/清空FIFO、设置触发阈值 |
| 中断使能寄存器 | IER | 读写 | 使能/屏蔽各类中断源 |
| 中断标识寄存器 | IIR | 只读 | 标识当前中断类型(优先级编码) |
驱动开发要点:
- 初始化顺序:配置LCR(帧格式)→ 设置DLL/DLH(波特率)→ 配置FCR(FIFO)→ 配置IER(中断)→ 使能UART。
- 发送流程:检查LSR的THR空标志 → 写入THR → 等待发送完成(或使用中断)。
- 接收流程:检查LSR的DR(数据就绪)标志 → 读取RBR → 检查LSR错误位。
- 中断处理:读取IIR判断中断类型 → 执行对应处理 → 清除中断源。
2.7 本章小结
UART控制器的硬件架构是驱动开发的基础。理解发送器与接收器的移位寄存器