2. UART硬件架构:发送器(TX)、接收器(RX)、波特率发生器、控制寄存器概览
UART(Universal Asynchronous Receiver/Transmitter)硬件模块是串行通信的物理基础。理解其内部架构——特别是发送器、接收器、波特率发生器以及控制寄存器的协同工作方式——是编写高效、稳定驱动的前提。本章将拆解UART核心单元,并建立它们之间的数据流与配置关系。
2.1 UART硬件模块顶层架构
一个典型的UART IP核(如16550兼容型)由以下四大功能块构成,它们通过内部总线与CPU交互,并通过外部引脚连接物理层(RS-232/485)。
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硬件:
- 设置波特率: 置位LCR的DLAB位 → 写DLL/DLM → 清除DLAB位。
- 配置数据格式: 写LCR设置数据位、停止位、校验位。
- 配置FIFO: 写FCR使能FIFO、设置触发阈值、清除FIFO。
- 配置中断: 写IER使能需要的中断类型。
- 配置流控(可选): 写MCR设置RTS/DTR或使能自动流控。
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管理策略,探讨如何利用这些硬件特性实现低延迟、高吞吐的驱动设计。