3.3 DW_apb_uart
3.3.1 概述
DW_apb_uart是新思科技提供的一款基于AMBA APB总线接口的通用异步收发器(UART)控制器,广泛应用于各类SoC中。
时序图如下:

核心特性如下:
1. 接口与时钟特性
- APB总线接口:支持AMBA APB接口,支持8、16、32位APB数据总线宽度,实现与系统总线的无缝连接。
- 时钟架构:支持单时钟(pclk,用于APB总线接口)或双时钟(pclk + sclk,sclk用于串口收发,支持跨时钟域同步),支持可编程小数分频的波特率生成。
2. 通信协议与帧格式特性
- 数据格式灵活:支持5~8bit数据位、1/1.5/2bit停止位,支持奇校验、偶校验、固定1/0校验及无校验。
- 9bit模式:支持9bit模式(第9位用于地址/数据区分),支持硬件/软件地址匹配,适用于一主多机通信场景。
- 错误检测:支持错误启动位检测、奇偶校验错误检测、帧错误检测及超时检测。
3. 缓冲与传输机制
- FIFO支持:支持可配置深度的FIFO(深度可配置为0/16/32/64/128/256/512/1024/2048),支持非FIFO模式(单字节收发)和FIFO模式,支持可编程的FIFO阈值(用于中断/DMA触发)。
- DMA支持:支持DMA方式收发数据,提供DMA请求/应答信号,支持可配置的触发流水线,降低CPU开销。
- 中断支持:支持多种中断(接收数据可用、发送保持寄存器空、接收超时、错误中断等),支持可编程的THRE(发送FIFO空阈值)中断模式。
4. 流控与接口模式
- 硬件流控:支持自动RTS/CTS流控,支持DTR/DSR流控,支持自动流控(Auto-RTS/Auto-CTS)以防止接收端溢出。
- 红外模式(IrDA SIR):支持红外通信模式(SIR),支持半双工通信,最高速率115.2kbps,支持红外脉冲编码。
- RS485模式:支持RS485接口,支持全双工、软件控制半双工、硬件控制半双工(通过TX FIFO状态自动切换DE/RE)模式,支持硬件自动流控及收发方向控制。
- 其他模式:支持内部回环(Loopback)模式,支持调制解调器(Modem)信号(RTS/CTS/DTR/DSR)控制。
5. 性能与配置特性
- 波特率配置:支持可编程小数分频,波特率计算公式为Baud = SCLK/(16×Divisor),分频系数支持整数和小数部分,支持高精度波特率设置。
- 可配置性:通过内部寄存器(如LCR、FCR、IER等)实现灵活配置,支持软件配置与硬件自动适应。
3.3.2 寄存器总览
DW_apb_uart的寄存器地址空间基于传统16550标准,但由于APB总线采用32位数据边界,每个寄存器偏移量为4字节。下表列出了所有寄存器的地址偏移及访问属性。
重要说明:DLAB是线控寄存器(LCR)的最高位,当DLAB=1时,偏移0x00、0x01处的寄存器被映射为波特率除数锁存器(DLL/DLM)当DLAB=0时,则映射为发送/接收缓冲区和中断使能寄存器。
| 偏移量 | DLAB=0 | DLAB=1 | 属性 | 寄存器名称 | 功能描述 |
|---|---|---|---|---|---|
| 0x00 | RBR | DLL | R/W | 接收缓冲寄存器/除数锁存低字节 | RBR:接收数据缓冲区;DLL:波特率除数低8位 |
| 0x00 | THR | DLL | R/W | 发送保持寄存器/除数锁存低字节 | THR:待发送数据写入;DLL:同上 |
| 0x04 | IER | DLM | R/W | 中断使能寄存器/除数锁存高字节 | IER:中断类型使能;DLM:波特率除数高8位 |
| 0x08 | IIR | - | R | 中断标识寄存器 | 标识当前待处理的中断类型及优先级 |
| 0x08 | FCR | - | W | FIFO控制寄存器 | FIFO使能、清空及触发阈值配置 |
| 0x0C | LCR | LCR | R/W | 线控寄存器 | 数据格式配置(数据位、停止位、校验位等) |
| 0x10 | MCR | MCR | R/W | 调制解调器控制寄存器 | 流控信号控制(RTS、DTR等) |
| 0x14 | LSR | LSR | R | 线状态寄存器 | 线路状态标志(数据就绪、溢出、错误等) |
| 0x18 | MSR | MSR | R | 调制解调器状态寄存器 | 调制解调器输入信号状态(CTS、DSR等) |
| 0x1c | SCR | SCR | R/W | 暂存寄存器 | 用户自定义临时存储 |
3.3.3 核心寄存器详解
**接收缓冲寄存器:**RBR保存从串行端口接收到的数据字节。当接收到完整的数据字节并经过校验后,数据被存入RBR,同时线状态寄存器的DR位被置1。CPU读取RBR后,DR位自动清零,bit0-bit7为接收数据字节。
**发送保持寄存器:**THR用于存放待发送的数据字节。CPU将数据写入THR后,数据被移入发送移位寄存器并逐位发送出去。线状态寄存器的THRE位指示THR是否为空,bit0-bit7为待发送数据字节。
中断使能寄存器:
| bit | 名称 | 功能描述 |
|---|---|---|
| 0 | ERBFI | 接收数据有效中断使能:1 = 使能RBR有数据时的中断 |
| 1 | ETBEI | 发送保持寄存器空中断使能:1 = 使能THRE中断 |
| 2 | ELSI | 接收线状态中断使能:1 = 使能线路状态错误(奇偶校验、帧错误等)中断 |
| 3 | EDSSI | 调制解调器状态中断使能:1 = 使能调制解调器输入信号变化中断 |
| 7:4 | - | 保留,写入0 |
说明:在UART初始化阶段,一般先向IER写入0以禁用所有中断,避免初始化过程中产生意外中断干扰。
中断标识寄存器:
| bit位 | 功能描述 |
|---|---|
| 0 | 中断挂起标志。0 = 有中断待处理;1 = 无中断待处理 |
| Bit3:1 | 中断类型编码(如下表) |
| Bit7:4 | FIFO使能标志(仅16550/16650模式),位7:6 = 11表示FIFO已使能 |
| 优先级 | IIR3:1 | 中断类型 | 中断源 | 清除方式 |
|---|---|---|---|---|
| 最高 | 011 | 接收线状态 | 奇偶校验错误、帧错误、溢出错误等 | 读LSR |
| 高 | 010 | 接收 数据可用 | RBR有数据(非FIFO模式)或达到接收FIFO触发阈值 | 读RBR直至低于阈值 |
| 高 | 110 | 字符超时 | 接收FIFO非空且一段时间无新数据(仅FIFO模式) | 读RBR |
| 低 | 001 | THRE | 发送保持寄存器空 | 写THR或读IIR |
| 最低 | 000 | 调制解调器状态 | CTS,DSR等输入信号变化 | 读MSR |
**FIFO控制寄存器:**FCR用于配置UART的FIFO操作模式。FCR只在16550/16650兼容模式下可用。
FCR常用配置值说明:
- 0x01:仅使能FIFO,不清空
- 0x07:使能FIFO并清空接收和发送FIFO
- 0xC7:使能FIFO、清空FIFO并设置接收触发阈值为14字节
| 位 | 名称 | 功能描述 |
|---|---|---|
| 0 | FIFO_EN | FIFO使能。1 = 使能发送和接收FIFO |
| 1 | RCVR_FIFO_CLR | 清空接收FIFO。写1清空接收FIFO计数器,该位自动清零 |
| 2 | XMIT_FIFO_CLR | 清空发送FIFO。写1清空发送FIFO计数器,该位自动清零 |
| 3 | DMA_MODE | DMA模式选择。0 = 单次DMA模式;1 = 多路DMA模式 |
| 5:4 | - | 保留 |
| 7:6 | RX_TRIGGER | 接收FIFO触发阈值。00 = 1字节;01 = 4字节;10 = 8字节;11 = 14字节 |
**线控寄存器:**LCR配置串行数据格式,包括数据位宽、停止位数、奇偶校验等。LCR最高位(bit7)是除数锁存访问位(DLAB)。UART帧通常由"起始位 + 数据位(字长位)+ 校验位(可选)+ 停止位"组成,字长决定了一帧数据中包含的bit数。
| 位 | 名称 | 功能描述 |
|---|---|---|
| 1:0 | WLS | 字长选择。00 = 5位;01 = 6位;10 = 7位;11 = 8位 |
| 2 | STB | 停止位数。0 = 1个停止位;1 = 1.5个停止位(5位 数据)或2个停止位(6/7/8位数据) |
| 3 | PEN | 奇偶校验使能。1 = 使能校验位发送和检测 |
| 4 | EPS | 偶校验选择。0 = 奇校验;1 = 偶校验(仅当PEN=1时有效) |
| 5 | SP | 粘附奇偶校验。强制校验位恒为0或1(仅当PEN=1时有效) |
| 6 | BC | 中断控制。1 = 强制串行输出持续为逻辑0(发送break条件) |
| 7 | DLBA | 除数锁存访问位。0 = 访问RBR/THR/IER;1 = 访问DLL/DLM |
**调制解调器控制寄存器:**MCR控制调制解调器接口的输出信号及UART辅助功能。
| 位 | 名称 | 功能描述 |
|---|---|---|
| 0 | DTR | 数据终端就绪。控制DTR_n输出引脚 |
| 1 | RTS | 请求发送。控制RTS_n输出引脚 |
| 2 | OUT1 | 用户自定义输出1 |
| 3 | OUT2 | 用户自定义输出2。通常用于中断输出使能 |
| 4 | LOOP | 回环模式。1 = 使能内部回环诊断模式 |
| 7:5 | - | 保留 |
**线状态寄存器:**LSR提供发送和接收数据路径的状态信息。
说明:当OE、PE、FE或BI中任一位置1时,LSR位0(DR)也会被置1,且会触发线状态中断(若使能)。读取LSR后,OE、PE、FE、BI位自动清零。
| 位 | 名称 | 功能描述 |
|---|---|---|
| 0 | DR | 接收数据就绪。1= RBR中有可读数据 |
| 1 | OE | 溢出错误。1=发生接收数据溢出(数据丢失) |
| 2 | PE | 奇偶校验错误。1=接收数据有奇偶校验错误 |
| 3 | FE | 帧错误。1=接收数据有帧错误(停止位不正确) |
| 4 | BI | 中断间隔。1=接收到break信号 |
| 5 | THRE | 发送保持寄存器空。1=THR为空,可写入新数据 |
| 6 | TEMT | 发送移位寄存器空。1=THR和发送移位寄存器均为空 |
| 7 | FIFO_ERROR | 接收FIFO中有错误数据(FIFO模式下有效) |
**调制解调器状态寄存器:**MSR提供调制解调器接口的输入信号状态及变化标志。
| 位 | 名称 | 功能描述 |
|---|---|---|
| 0 | DCTS | CTS输入变化标志。读MSR后自动清零 |
| 1 | DDSR | DSR输入变化标志。读MSR后自动清零 |
| 2 | TERI | RI输入变化标志(下降沿)。读MSR后自动清零 |
| 3 | DDCD | DCD输入变化标志。读MSR后自动清零 |
| 4 | CTS | 清除发送输入状态 |
| 5 | DSR | 数据设备就绪输入状态 |
| 6 | RI | 振铃指示输入状态 |
| 7 | DCD | 载波检测输入状态 |
除数锁存寄存器(DLL/DLM):
DLL和DLM构成16位波特率除数。波特率计算公式为:Divisor = 时钟频率 / (波特率 × 16)
DLL保存Divisor值的低8位,DLM保存Divisor值的高8位。
3.3.4 编程概要
初始化流程:
void uart_init(void)
{
unsigned int divisor = uart_clock/(baud_rate * 16);
//1. 禁用所有中断
writeb(0, UART_IER);
//2. 设置DLAB=1,配置波特率除数
writeb(0x80, UART_LCR); //设置DLAB=1
writeb(divisor & 0xFF, UART_DLL); //除数低字节
writeb((divisor >> 8) & 0xFF, UART_DLM); //除数高字节
//3. 配置串行数据格式(8位数据、1停止位、无校验)
writeb(0x03, UART_LCR); //DLAB=0, WLS=8位
//4. 配置FIFO(使能FIFO,清空FIFO,设置触发阈值)
writeb(0xC7, UART_FCR); //FIFO使能+清空+14字节阈值
//5. 按需使能中断
//writeb(IER_ERBFI | IER_ELSI, UART_IER);
}
数据发送:
void uart_putc(char ch)
{
//等待THRE为1(发送保持寄存器为空)
while (!(readb(UART_LSR) & LSR_THRE));
writeb(ch, UART_THR);
}
数据接收:
char uart_getc(void)
{
//等待DR为1(接收数据就绪)
while (!(readb(UART_LSR) & LSR_DR));
return readb(UART_RBR);
}