在嵌入式系统开发中,UART(Universal Asynchronous Receiver/Transmitter)作为最基础的串行通信接口,其重要性不言而喻。ARM架构下的UART控制器通过精心设计的寄存器组实现了高度可配置的通信功能。让我们先来认识这些核心寄存器:
寄存器分类与功能概览:
关键提示:所有寄存器的修改必须在UART禁用状态下进行,修改完成后需要重新使能。突然修改活跃状态的寄存器可能导致数据丢失或通信异常。
ARM UART的波特率生成采用经典的16倍过采样技术,其核心计算公式为:
code复制BAUDDIV = (FUARTCLK/(16×Baud rate))
其中BAUDDIV由整数部分(UARTIBRD)和分数部分(UARTFBRD)组成。分数分频通过6位精度的UARTFBRD寄存器实现,其转换公式为:
code复制BRDF = UARTFBRD/64
误差控制原理:
c复制// 计算步骤
BAUDDIV = 4000000/(16×230400) ≈ 1.085
整数部分 BRDI = 1
分数部分 BRDF = 0.085
UARTFBRD = round(0.085×64) = 5
实际分频值 = 1 + 5/64 ≈ 1.078
实际波特率 = 4000000/(16×1.078) ≈ 231911
误差 = (231911-230400)/230400 ≈ 0.656%
不同应用场景下,时钟源的选择直接影响波特率精度。以下是两种常见配置:
7.3728MHz时钟的整数分频(无分数误差):
| 波特率(bps) | UARTIBRD值 | 十六进制 |
|---|---|---|
| 460800 | 1 | 0x1 |
| 115200 | 4 | 0x4 |
| 57600 | 8 | 0x8 |
| 9600 | 48 | 0x30 |
4MHz时钟的分数分频配置:
| 目标波特率 | UARTIBRD | UARTFBRD | 实际波特率 | 误差率 |
|---|---|---|---|---|
| 230400 | 0x1 | 0x5 | 231911 | 0.656% |
| 115200 | 0x2 | 0xB | 115101 | 0.086% |
| 38400 | 0x6 | 0x21 | 38369 | 0.081% |
正确的寄存器配置顺序对确保通信稳定至关重要:
关键注意事项:
通过UARTLCR_H寄存器可以灵活定义通信协议:
c复制// 典型8N1配置(8数据位,无校验,1停止位)
UARTLCR_H = (3 << 5); // WLEN=11(8位), FEN=0(禁用FIFO), STP2=0(1停止位)
// 7E1配置(7数据位,偶校验,1停止位)
UARTLCR_H = (2 << 5) | (1 << 3) | (1 << 1); // WLEN=10, EPS=1, PEN=1
奇偶校验真值表:
| PEN | EPS | SPS | 校验类型 |
|---|---|---|---|
| 0 | X | X | 无校验 |
| 1 | 1 | 0 | 偶校验 |
| 1 | 0 | 0 | 奇校验 |
| 1 | 0 | 1 | 强制为1 |
| 1 | 1 | 1 | 强制为0 |
通过UARTCR寄存器启用RTS/CTS流控:
c复制// 启用CTS流控(发送受CTS信号控制)
UARTCR |= (1 << 15); // CTSEn=1
// 启用RTS流控(接收缓冲区满时拉高RTS)
UARTCR |= (1 << 14); // RTSEn=1
实践经验:在工业环境中,硬件流控能有效避免数据丢失,特别是在电磁干扰较强的场合。但需注意连接器必须正确接线,误接可能导致通信完全阻塞。
中断阈值设置(UARTIFLS):
c复制// 接收FIFO达到1/2时触发中断
UARTIFLS = (2 << 3); // RXIFLSEL=010
// 发送FIFO剩余1/4空间时触发中断
UARTIFLS |= (1 << 0); // TXIFLSEL=001
DMA配置示例:
c复制UARTDMACR = 0x3; // 使能收发DMA
UARTCR |= (1 << 9) | (1 << 8); // 使能收发功能
通信异常排查清单:
波特率精度优化技巧:
通过UARTCR启用IrDA模式:
c复制UARTCR |= (1 << 1); // SIREN=1
UARTCR &= ~(1 << 2); // SIRLP=0(标准3/16脉冲)
硬件环回测试配置:
c复制UARTCR |= (1 << 7); // LBE=1(启用环回)
UARTTCR |= (1 << 2); // SIRTEST=1(全双工测试)
测试数据收发验证:
c复制// 写入测试数据
UARTDR = 0x55;
// 读取应返回相同数据
if(UARTDR != 0x55) {
// 测试失败处理
}