Skip to content

先搞懂它是什么

  • UART(通用异步收发器):用两根线(TX 发、RX 收)逐位传数据的串行接口,电脑串口、传感器、蓝牙模块调试口大多用它。
  • 异步:收发双方没有时钟线,靠双方约定好的“波特率”和对齐方式自己数位,所以收发波特率必须一致。
  • 为什么必学:串口是嵌入式开发最常用的“日志出口”和调试手段,SDK 例程统一用 2000000 波特率打印日志,就是这个道理。

层层拆解原理

1. 帧格式:一个字节怎么传

空闲时 TX 保持高电平。发送一个字节按下面的顺序走:

  • 起始位:把线拉低,接收方据此对齐后续位数。
  • 数据位:常见 8 位(即 8N1 中的 8)。
  • 校验位:可选的奇偶校验,用于查错不纠错。
  • 停止位:恢复高电平,准备下一帧。

“8N1”的意思是:8 位数据、无校验(None)、1 位停止位——大多数嵌入式串口默认配置。

2. 波特率:双方怎么“数位”

波特率 = 每秒传输的位数(bit/s)。发送方按波特率把每一位“铺”在线上,接收方用同一个波特率采样。只要波特率不一致,接收方就会把位“数错”,得到乱码。

波特率是由外设时钟分频得到的,所以“换时钟源/改分频后没重新算波特率”也会导致乱码。

3. 电平与接口形态

形态电平标准典型场景
TTL 电平0~3.3V/5VMCU 与传感器/模组直连
RS-232±12V 左右老式电脑串口,需电平转换芯片
USB 转串口芯片转换电脑调试(如 CH340/CP2102)

开发板上的 USB 口通常内置了 USB 转串口芯片,所以电脑上看到的是 COM 口,板子内部实际是 TTL 串口。

4. 数据流向:读缓冲与写缓冲

MCU 的 UART 外设一般带接收 FIFO:数据到达后先存进 FIFO,程序稍后去读;程序也可以先写发送 FIFO,由硬件按波特率慢慢发出去。这样程序不必逐位等待,效率更高。

进阶用法:

  • 中断接收:有数据到达时触发中断,程序在中断里收数据,不阻塞主流程。
  • DMA 接收:硬件把 FIFO 里的数据直接搬进内存,CPU 完全不用参与,适合大数据量传输。
  • 流控(RTS/CTS):双方通过额外引脚通知“我忙/我可以收”,防止数据丢失。

结合 SDK 看实现

SDK 里串口初始化同样是“定义设备结构体 → 配置参数 → 收发数据”的套路(WB2 SDK 使用 HOSAL 统一外设层,配置直接写在 hosal_uart_dev_t 结构体的 config 字段里):

c
hosal_uart_dev_t uart0;   /* 直接定义设备结构体,无需 get_by_name */
/* 配置 2000000 波特率,8 数据位,无校验,1 停止位 */
uart0.config.uart_id = 0;
uart0.config.baud_rate = 2000000;
uart0.config.data_width = HOSAL_DATA_WIDTH_8BIT;
uart0.config.parity = HOSAL_NO_PARITY;
uart0.config.stop_bits = HOSAL_STOP_BITS_1;
uart0.config.mode = HOSAL_UART_MODE_POLL;   /* 轮询收发 */
hosal_uart_init(&uart0);

打印日志用的 printf 最终也是往这个串口 FIFO 里写数据,再由硬件一位一位发出去——所以“printf 能打印”就说明 UART 通路正常。

常见考点 / 面试题

什么是 8N1?

8 位数据位、无校验位(None)、1 位停止位,是嵌入式串口最常见的帧格式;收发双方必须配置一致。

串口乱码最常见的原因是什么?

波特率不一致(或时钟/分频被改导致波特率计算偏差)、接线 RX/TX 接反、共地问题。先核对波特率,再看接线。

UART 是全双工吗?

是。TX 和 RX 是独立的两根线,可以同时收发;这是它相比 I2C/SPI 共享时钟线的不同点之一。

为什么传数据要分“起始位/数据位/停止位”?

因为没有时钟线,接收方要靠起始位的下降沿对齐采样时刻,数据位承载内容,停止位保证帧与帧之间有明确边界。

中断接收和 DMA 接收有什么区别?

中断接收:每个数据到达都打断 CPU 去搬运,适合小数据量;DMA:硬件直接搬数据到内存,CPU 空闲,适合大批量或高速传输。

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23