树莓派 Pico UART 底层全解析:从硬件架构到寄存器操作的硬核指南
树莓派 Pico 上的 UART 串口外设是树莓派 Pico 上的 “串行通信单元”,专门负责 Pico 和其他设备(比如电脑、传感器、显示屏)之间使用串口协议进行通信:
-
发数据:Pico 内部的并行数据通过 UART 转成串行数据传给外部设备;
-
收数据:外部设备的串行数据通过 UART 转成并行数据传给 Pico 内部。
串口外设不是一个单独工作的单元,而是一个需要和 Pico 内部的其他部件配合的工作单元:
-
CPU:负责发指令、处理最终数据;
-
UART 外设:负责数据的串并转换和不同设备的串口编解码;
-
AMBA APB 总线:CPU 通过 AMBA APB 总线对 UART 外设进行控制和传输数据;
-
FIFO 存储器:UART 接收和发送的数据可由 FIFO 存储器进行缓存,FIFO 缓存器最高支持 32 字节数据在传输和接收模式下独立存储。
![image.png]()
串口外设支持如下功能:
- 可编程的波特率发生器:生成与目标通信速率匹配的时钟信号,实现 UART 与外部设备的 “波特率同步”(如 9600、115200 等),是异步通信的基础;
- 提供了类似于行业标准的 16C650 UART 设备的功能:遵循通用的 UART 硬件协议,确保 Pico 的 UART 可与主流 UART 设备(如电脑、传感器)直接通信,具备良好的互操作性;
- 在系统时钟为 125MHz 时,速率最大支持 7.8Mbps:指 UART 的理论带宽上限,日常常用的低速通信(如 9600bps)远低于此值,可满足多数场景的传输需求;
- 来自于接收、发送、调制器模式和错误调节的独立可屏蔽中断:UART 针对 “接收完成、发送完成、调制器状态变化、通信错误” 等事件,提供独立的中断源;CPU 可通过寄存器屏蔽特定中断,仅响应需要的事件,减少不必要的 CPU 资源占用;
- 对 DMA 控制器发送 DMA 请求:UART 可向 DMA 控制器发起 “数据传输请求”,触发 DMA 完成 “FIFO 与内存之间的数据搬运”(无需 CPU 介入),降低 CPU 的负载;
- 有一个可编程的硬件流控制特性:通过 nUARTCTS(清除发送)和 nUARTRTS(请求发送)引脚,实现收发端的流量控制,当接收端缓存满时,通过 CTS 引脚通知发送端暂停传输;接收端就绪后,再通过 CTS 允许传输,避免数据溢出。
![image.png]()
当 UART 接收数据时,若出现异常,会通过寄存器标记并保护数据:
- 若发生帧错误、奇偶校验错误、断开错误:UART 会设置对应寄存器的 “错误标志位”,同时将错误数据存入接收 FIFO,供 CPU 后续处理;
- 若发生 FIFO 溢出(接收数据量超过 FIFO 容量):UART 会立即设置 “溢出标志位”,并停止接收新数据,防止已存入 FIFO 的有效数据被覆盖。
1.UART 外设结构
树莓派 Pico 的串口外设基本结构框图如下:

上面框图是树莓派 Pico 串口外设 UART 的 “内部工作流水线”,每个模块分工明确,共同完成串行通信:
- 核心控制入口:
AMBA APB接口和寄存器组,这是CPU与UART通信的唯一窗口:AMBA APB接口:CPU通过这个接口,向UART下发 “控制指令”(比如设置波特率)、写入 “待发送数据”,或读取 “已接收数据”“UART 工作状态”;- 寄存器组:存储 UART 的控制参数(如波特率配置)、状态信息(如 FIFO 是否满),以及临时数据 —— 相当于 UART 的 “控制面板 + 临时记事本”。
- 时钟同步核心:波特率生成器
- 它是
UART的 “节拍器”,负责生成与目标波特率匹配的时钟信号; - 工作逻辑:从系统时钟(
UARTCLK)出发,通过 “分频” 生成Baud16时钟(正常模式下使用)——Baud16是 16 倍目标波特率的时钟(比如目标波特率是 9600,则 Baud16 是 153600); - 作用:发射器 / 接收器会将
Baud16除以 16,得到 “1 倍波特率” 的时钟,用于同步数据的发送 / 接收(接收时可在每个数据位的中间采样,减少电平判断错误)。
- 它是
- 数据缓存区:
FIFO存储器:- 分为发送
FIFO和接收FIFO,是缓解 “CPU与UART速率差异” 的关键; - 发送
FIFO(32×8 位):CPU 先将待发送的 8 位数据写入这里,发射器会从 FIFO 中逐字节取出,转成串行数据发送,即使 CPU 处理速度慢,数据也能暂存不丢失; - 接收
FIFO(32×12 位):接收器将收到的串行数据转成并行数据后,连同 “错误标志位”(如帧错误)一起存入这里(12 位包含 8 位数据 + 4 位错误信息),等待 CPU 读取,避免接收器收到数据时 CPU 忙而丢数据。
- 分为发送
- 数据收发执行:发射器(Transmitter)& 接收器(Receiver)
- 这是 UART 的 “执行单元”,完成串行 - 并行的转换;
- 发射器:从发送 FIFO 读取并行数据,在
Baud16时钟的同步下,将数据逐位转为串行信号,从UARTTXD引脚发送出去; - 接收器:从
UARTRXD引脚接收串行信号,在Baud16时钟的同步下,将信号逐位转为并行数据,存入接收 FIFO(同时标记错误状态)。
- 状态通知:中断发生器
- 它是 UART 的 “状态播报员”;
- 收集 FIFO 的状态(如发送 FIFO 空、接收 FIFO 满)、收发事件(如发送完成、接收完成)、通信错误(如帧错误)等信号;
- 将这些信号做 “OR 运算”(即任意一个事件发生都触发),生成中断信号发送给 CPU,让 CPU 及时处理(比如读取接收数据、处理错误)。
- 高效数据搬运:DMA 接口
- 这是 UART 与 DMA 控制器的 “连接口”;
- 当 FIFO 中数据达到一定量时,UART 会通过这个接口向 DMA 发起 “传输请求”;
- DMA 收到请求后,会自动将 “发送 FIFO 与内存”“接收 FIFO 与内存” 之间的数据搬运,全程无需 CPU 参与,降低 CPU 负载。
整体工作流程为:
- 发送流程:CPU → (APB 接口)写数据到发送 FIFO → 波特率生成器产生 Baud16 时钟 → 发射器从 FIFO 取数据 → 转串行数据从 UARTTXD 发出;
- 接收流程:UARTRXD 接收串行数据 → 接收器(用 Baud16 时钟)转并行数据 + 标记错误 → 存入接收 FIFO → 中断发生器通知 CPU → CPU(APB 接口)读接收 FIFO 数据。
这里,波特率生成器会提供两个时钟信号,IrLPBaud16 和 Baud16:
IrLPBaud16:提供给串口发射器和接收器的时钟信号,在 IrDA 红外模式下使用,这里不做讲解Baud16:提供给串口发射器和接收器的时钟信号,产生一个 16× 波特率下的整数波特率参考时钟,脉宽为一个 UARTCLK 时钟周期,在正常模式下使用,将该时钟信号除以 16 以产生串口发射器的时钟
2.UARTCLK 的时钟配置
UARTCLK 的频率需要适应于波特率的范围:
16 × 波特率最大值 ≤ UARTCLK 的频率 ≤ 6×65535× 波特率最小值
例如,波特率在 110 到 460800 之间时,UARTCLK 频率必须在 7.3728MHz 到 115.34MHz 之间。
同时,UARTCLK 的频率与 PCLK 的频率比值必须小于等于 5/3,即:
UARTCLK 的频率 ≤ 5/3 × PCLK 的频率
例如,在 UART 模式下,当 UARTCLK 为 14.7456MHz 时,要生成 921600 波特,那么 PCLK 必须大于或等于 8.85276MHz。这确保了 UART 有足够的时间将接收到的数据写入接收到的 FIFO。
3.UART 外设操作
UART0 和 UART1 寄存器的基地址为 0x40034000 和 0x40038000。
通过写入 UARTLCR 寄存器可以控制 UART 外设,该寄存器内部有 30 个位,需要注意的是,我们需要在外部通过 APB 总线接口访问 UARTLCR_H、UARTIBRD 和 UARTFBRD 寄存器来写入 UARTLCR 寄存器,其中:
-
UARTLCR_H 寄存器:
主要用于定义传输的有效数据、数据位数、停止位数、校验位、传输流模式、断开连接

- UARTIBRD 寄存器:定义了波特率除数因子的整数部分

- UARTFBRD 寄存器:定义了波特率除数因子的小数部分

3.1 设置波特率
设置波特率主要是对波特率除数因子进行设置(以下简称波特率因子),波特率因子为一个 22bit 数字,包含一个 16bit 整数部分和一个 6bit 小数部分。小数波特率因子允许任何频率大于 3.6864MHz 的时钟作为 UARTCLK,同时仍然可以产生所有标准波特率。
16 位的整数波特率因子由 UARTIBRD 寄存器载入,6 位的小数波特率因子由 UARTFBRD 寄存器载入。
波特率因子与 UARTCLK 时钟的关系为:
BRD = BRDI + BRDF = UARTCLK/(16×Baud Rate),其中 BRDI 是 BRD 的整数部分,BRDF 是小数部分,由小数点分离,UARTCLK 是连接至 UART 的系统时钟。

3.2 错误位
三个错误位存储在接收 FIFO 存储器的位[10:8]中,并与一个特定的字符相关联。还有一个附加错误表示 overrun 溢出错误,它存储在接收 FIFO 的第 11 位。

在 FIFO 存储器已满时,将 overrun 设置溢出错误,接着下一个数据便会直接写入到 UART 的移位寄存器中(移位寄存器主要用于串口数据的串并转换),并且覆盖当前存储在 UART 移位寄存器中的数据。当接收 FIFO 中的空位置可用,并且接收到另一个字符时,溢出位的状态与接收到的字符一起复制到接收 FIFO 中,然后将清除溢出状态。
关于错误位的读取,主要通过访问 UARTDR 寄存器来完成:

3.3 系统诊断和回环测试
通过设置 UARTCTL 寄存器的 LBE 位可将 UART 设为内部回环模式,以用于诊断或调试工作。在回环模式中,UARTxTXD 输出的发送数据会被 UARTxRXD 输入接收。注意,LBE 位应在 UART 启用前设置。

3.4 FIFO 操作
UART 有两个独立的 FIFO 存储器:独立的 32×8 Tx 发送 FIFO 存储器 和 32×12 Rx 接收 FIFO 存储器。两个 FIFO 都通过 UARTDR 寄存器访问。UARTDR 寄存器读操作返回一个 12bit 值,它由 8 个数据位和 4 个错误标志位组成,而写操作将 8bit 数据放入发送 FIFO。
我们可以通过设置 UARTLCR_H 寄存器的 FEN 位来控制 FIFO 的工作模式:
- FEN = 0:FIFO 被禁用,工作在字符模式,保持为 1 字节深度寄存器
- FEN = 1:FIFO 启用,工作在 FIFO 模式,传输和接收 FIFO 缓冲区被启用

FIFO 的状态可通过 UART Flag(UARTFR)寄存器和 UART Receive Status(UARTRSR)寄存器来监测其是否处于空、满、溢出状态。
UARTFR 寄存器包含空和满标志位(TXFE、TXFF、RXFE 和 RXFF 位):

如果禁用 FIFO,则空和满标志位则按照 1 字节深度寄存器状态进行设置。
UARTRSR 寄存器通过 OE 位显示溢出状态:

4.UART 收发流程
4.1 UART 数据发送流程

- APB 总线可以访问状态/控制寄存器, 并将需要发送的信息存入发送 FIFO 存储器;
- 波特率生成器从 APB 总线和寄存器块中获取波特率分频因子,产生内部时钟-Baud16,频率为波特率的 16 倍;
- UART 发送器受到状态/控制寄存器控制,以 Baud16 为时钟源将发送 FIFO 存储器中的内容逐个发送;
- FIFO 状态和中断生成器会根据 FIFO 存储器的内容生成对应的 FIFO 标志位和中断信号
4.2 UART 数据接收流程

- UART 接收器受到状态/控制寄存器控制,以 Baud16 为时钟源,将接收到的信息存入接收 FIFO 存储器中;
- APB 总线可以通过读取接收 FIFO 获取读取值
5.UART 硬件流控功能
我们可以通过使用 nUARTRTS 输出和 nUARTCTS 输入信号来控制串行数据流:

当 RTS 流控开启时,接收 FIFO 存储器会在数据填充至设定的缓存深度时,nUARTRTS 输出信号会至高电平-无效,在此之前,nUARTRTS 输出信号会一直保持低电平-有效来指示 FIFO 状态;当 CTS 流控开启时,串口发射器只有在接收到外部设备给 CTS 置低电平时,才会开始发送数据。
可以通过配置 UARTIFLS 寄存器来设置 FIFO 存储器的缓存深度:

可以使用控制寄存器 UARTCR 中的 RTSEn 和 CTSEn 位来选择硬件流控制:


需要注意的是,一旦启用 RTS 流控制(即设置 RTSEN 位为 1)后,软件便不能使用控制寄存器 UARTCR 中的 RTSEn 位来控制 nUARTRTS 的状态,也不能更改 nUARTRTS 的输出值。


6.UART 的 DMA 接口
UART 提供了到 DMA 控制器的接口,并有单独的发送和接收通道。通过 UART DMA Control(UARTDMACR)寄存器来启动 UART 的 DMA 操作。DMA 在 DMA 请求信号后(外设完成一件事件后发出或者外设的状态已经准备好发出)进行数据传输,DMA 请求信号的产生来自于外设中与数据传输相关的寄存器,它们保存着外设当前工作的状态情况,在符合条件下向 DMA 发出请求。

可以产生的 DMA 请求包括:
- 对于接收端:

- 对于发送端:

简单来说,对于接收端而言只要在接收 FIFO 中存在数据,会产生单个传输请求 UARTRXDMASREQ,而当接收 FIFO 数据量大于等于 UARTIFLS 寄存器所配置的 FIFO 缓存深度时会产生一个突发传输请求 UARTRXDMABREQ;对于发送端来说,只要发送 FIFO 中存在至少一个空位,都会产生单个的传输请求 UARTTXDMASREQ,而只要发送 FIFO 所包含的字符少于 FIFO 触发水平,都会产生突发请求 UARTTXDMABREQ。对于接收端和发送端两方,DMA 控制器还可以产生 UARTTXDMACLR 和 UARTRXDMACLR 请求,在数据传输完毕后清除 DMA 的数据传输请求信号。
同时各个 DMA 请求可以同时发生,单个和突发传输请求否由 DMA 控制器自动处理、数据传输由单次模式还是突发传输模式进行取决于设置的 FIFO 存储器缓存深度和 FIFO 中的数据量。

7.UART 的中断
7.1 UART 中断类型
当检测到以下条件时,UART 会产生中断:
- 调制解调器状态信号变化:产生
UARTMSINTR中断 - 接收已满:产生
UARTRXINTR中断 - 发送不满:产生
UARTTXINTR中断 - 接收超时:产生
UARTRTINTR中断 - 接收错误:产生
UARTEINTR中断,包括以下错误情况:- 帧错误
- 奇偶校验错误
- 溢出错误
- Break 错误
![image.png]()
7.2 UART 中断的启用和禁用
中断事件可触发一个控制器级别中断,我们可以通过置位或复位 UARTIMSC( Interrupt Mask Set/Clear Register)寄存器中的各个位来启用或禁用各个中断:

7.3 UART 中断状态的读取
如果中断被屏蔽,源中断状态总是可以通过 UART Raw Interrupt Status (UARTRIS)寄存器可见:


在 UART 中有 11 个可屏蔽中断,这 11 个中断在进行 OR 运算后都连接到了 UARTINTR 上,UARTINTR 连接到了系统中断控制器中。UART 在任意给定时间仅能向控制器产生单个中断请求,软件则可以通过读取 UART Masked Interrupt Status(UARTMIS)寄存器以在单个中断服务程序中服务多个中断事件:

7.4 FIFO 的中断操作
FIFO 产生中断的缓存深度可由 UART Interrupt FIFO Level Select (UARTIFLS)寄存器控制,两个 FIFO 可单独配置以在不同水平上触发中断:


树莓派 Pico 上的 UART 串口外设是树莓派 Pico 上的 “串行通信单元”,专门负责 Pico 和其他设备(比如电脑、传感器、显示屏)之间使用串口协议进行通信:



浙公网安备 33010602011771号