目录
UART 是一种简单的串行通信协议,常用于微控制器、传感器和计算机之间的数据交换。它不像 I2C 或 SPI 那样需要共享时钟线,而是异步的,这意味着它更灵活,但也需要双方约定好通信速度。为什么 UART 这么受欢迎?因为它实现简单、成本低,且在短距离通信中可靠。在这篇长文中,我将详细拆解 UART 的每一个方面,包括原理、工作机制、配置、常见问题和实际应用。准备好你的咖啡,我们开始吧!
UART 的起源与历史
UART 的历史可以追溯到上世纪60年代的电传打字机时代。那时,计算机需要与外部设备通信,而串行通信是最经济的方式。UART 芯片如 Intel 8251 或 Motorola 6850 成为标准组件。
快进到今天,UART 已被集成到几乎所有微控制器(如 AVR、STM32、ESP32)中。它演变为更现代的变体,如 UART over USB(例如 FTDI 芯片)。理解历史有助于我们欣赏它的简洁性:UART 设计时考虑了噪声环境下的可靠性,而非高速传输(典型速度从 300 baud 到 115200 baud,甚至更高)。
UART 的基本原理:异步串行通信
UART 是异步的,这意味着发送方和接收方没有共享的时钟信号。相反,它们通过预设的**波特率(baud rate)**来同步。波特率表示每秒传输的位数,例如 9600 baud 意味着每秒 9600 位。
关键组件
- TX(Transmit)线:发送数据。
- RX(Receive)线:接收数据。
- GND(Ground):公共地线,确保信号参考一致。
- 可选:RTS/CTS 用于流控制(稍后详解)。
通信是单向的( simplex ),但通过交叉连接 TX 和 RX,可以实现全双工(full-duplex)。
数据帧结构
UART 数据以**帧(frame)**形式传输。每帧包括:
- 起始位(Start Bit):总是低电平(0),用于通知接收方数据即将到来。
- 数据位(Data Bits):通常 8 位(一个字节),但可以是 5-9 位。最低有效位(LSB)先传。
- 奇偶校验位(Parity Bit,可选):用于错误检测。即使校验(even parity):总1的个数为偶数;奇校验(odd parity):为奇数。
- 停止位(Stop Bits):1 或 2 个高电平(1),标记帧结束。
一个典型的 8N1 配置(8 数据位、无奇偶、1 停止位)的帧看起来像这样:
闲置状态 (高电平) ─────┐
│
起始位 (0) ┌─────┘
数据位 (LSB 先) │ 位0 位1 位2 位3 位4 位5 位6 位7
奇偶位 (可选) │ (P)
停止位 (1 或 2) │ 停止1 (停止2)
闲置状态 └───── 返回高电平
在实际波形中,这是一个方波信号。接收方在检测到起始位的下降沿后,开始采样后续位。
帧配置的常见变体
使用表格来清晰呈现:
配置 | 数据位 | 奇偶校验 | 停止位 | 描述 |
---|---|---|---|---|
8N1 | 8 | 无 | 1 | 最常见,用于 ASCII |
7E1 | 7 | 偶 | 1 | 用于一些旧系统 |
8O2 | 8 | 奇 | 2 | 提高可靠性 |
9N1 | 9 | 无 | 1 | 用于地址/数据分离 |
选择配置取决于应用:例如,工业环境中用奇偶校验防噪声。
UART 如何工作:发送与接收过程
发送过程
- 空闲状态:TX 线保持高电平。
- 起始位:当有数据要发时,拉低 TX 线一个位时长。
- 数据位:按波特率时钟发送每个位,从 LSB 开始。
- 奇偶位(如果启用):计算并发送。
- 停止位:发送 1 或 2 个高电平位。
- 返回空闲:如果有更多数据,继续;否则保持高。
发送方使用内部定时器生成位时序。
接收过程
- 检测起始位:接收方不断采样 RX 线,检测下降沿。
- 采样数据:从起始位中间开始采样(避免边缘噪声),每位时长采样一次。通常过采样(e.g., 16x 波特率)以提高精度。
- 校验奇偶(如果启用):如果不匹配,标记错误。
- 检查停止位:如果不是高,可能是帧错误。
- 处理数据:将位组装成字节,通知上层软件。
关键挑战:时钟漂移。由于异步,发送方和接收方的晶振可能有轻微差异(<1%)。过采样帮助校正,但长帧或低质量晶振可能导致错误。
波特率与时序
波特率 = 1 / 位时长。例如,9600 baud 的位时长 ≈ 104 μs。
计算公式:位时长 = 1 / 波特率。
双方必须匹配波特率!常见值:300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200。
在微控制器中,通过分频器设置:e.g., 在 AVR 上,UBRR = (F_CPU / (16 * baud)) - 1。
错误检测与处理
UART 不是完美的,尤其在噪声环境中。常见错误:
- 帧错误(Framing Error):停止位不是高,可能由于波特率不匹配。
- 奇偶错误(Parity Error):奇偶位不符。
- 溢出错误(Overrun Error):接收缓冲区满,未及时读取。
- 噪声错误:外部干扰导致位翻转。
解决方案:
- 使用奇偶校验。
- 启用硬件流控制(RTS/CTS):RTS(Request to Send)表示“我准备好发送”;CTS(Clear to Send)表示“我准备好接收”。
- 软件流控制:用 XON/XOFF 字符(Ctrl-Q/Ctrl-S)。
- CRC 或校验和在上层协议中添加。
UART 的硬件实现
电平标准
UART 信号通常是 TTL 电平(0-5V 或 0-3.3V),但在长距离传输中用 RS-232(-12V 到 +12V)以抗噪声。现代设备常用 USB-UART 桥接器,如 CH340 或 CP2102。
连接示例:
- 微控制器 TX → 另一设备 RX
- 微控制器 RX → 另一设备 TX
- 共享 GND
在微控制器中的集成
大多数 MCU 有硬件 UART 外设:
- 寄存器:数据寄存器 (UDR)、控制寄存器 (UCSR)、波特率寄存器 (UBRR)。
- 中断:RX 完成中断、TX 完成中断,便于异步处理。
软件 UART(bit-banging)也可实现,但效率低。
实际应用与示例
示例1:Arduino 中的 UART
Arduino Uno 使用 UART 与 PC 通信(Serial Monitor)。
代码示例(发送 “Hello World”):
void setup() {
Serial.begin(9600); // 设置波特率
}
void loop() {
Serial.println("Hello World"); // 发送数据
delay(1000);
}
接收示例:
void loop() {
if (Serial.available() > 0) {
char data = Serial.read();
Serial.print("Received: ");
Serial.println(data);
}
}
示例2:ESP32 与传感器通信
ESP32 有多个 UART 实例。连接 DHT11 传感器:
- 配置 UART2 为 9600 baud。
- 发送命令,读取温度/湿度。
高级应用
- Bluetooth 模块(如 HC-05):用 UART 配置和传输数据。
- GPS 模块:NMEA 协议基于 UART。
- Modbus 协议:工业自动化中 UART 的扩展。
- 多设备网络:用 RS-485(半双工变体)实现。
调试技巧:用逻辑分析仪捕获波形,或软件如 PuTTY 测试串口。
常见问题排查
- 无响应:检查波特率、连接(TX-RX 交叉?)。
- 乱码:波特率不匹配或电平不兼容(3.3V vs 5V)。
- 数据丢失:缓冲区溢出;用流控制。
- 长距离问题:用 RS-232 或屏蔽线。
UART 的优缺点
优点:
- 简单、线少(只需2-4线)。
- 全双工。
- 广泛支持。
缺点:
- 低速(<10Mbps)。
- 无内置寻址(不像 I2C)。
- 对噪声敏感。
相比其他协议:
- vs SPI:SPI 更快,但需要时钟线。
- vs I2C:I2C 支持多设备,但半双工。