1. UART协议基础:从历史到实战

大家好,我是你们的嵌入式讲师。今天咱们聊聊UART——这个看起来老掉牙、但每个嵌入式工程师都绕不开的串行通信协议。

说实话,我入行那会儿,UART已经存在几十年了。但直到现在,我调试过的板子里,十块有八块还在用UART做调试口。为什么?因为它简单、可靠、够用。

1.1 UART的历史:一个老而弥坚的协议

UART的全称是Universal Asynchronous Receiver/Transmitter,通用异步收发器。这玩意儿最早可以追溯到1960年代,当时IBM和DEC等公司开始用串行方式连接终端和主机。

我记得第一次在教科书上看到UART的发明时间,心里想:这也太老了吧?但后来在项目中吃过亏才明白——老不代表落后,稳定才是硬道理。

UART的关键里程碑:

年代 事件 影响
1960s 串行通信雏形出现 用于大型机与终端连接
1970s UART芯片化(如8250) 降低了实现成本
1980s PC标准集成UART RS-232成为标配
1990s至今 MCU内置UART外设 嵌入式系统广泛采用

你想想看,一个从大型机时代走过来的协议,到现在还在用,说明它确实有两把刷子。

1.2 异步串行通信原理:没有时钟线怎么传数据?

很多新手问我:UART只有两根数据线(TX和RX),没有时钟线,两边怎么同步?

这个问题问得好。UART用的是异步通信,说白了就是双方事先约定好速度,然后各自用自己的时钟来采样。

打个比方:两个人约好每秒钟说一个字,一个人说,另一个人听。说的人按自己的节奏说,听的人按自己的节奏听。只要两个人的节奏差不多,就能听懂。

这个约定的速度就是波特率(Baud Rate)。常见的波特率有9600、115200等。

关键点:UART通信双方必须使用相同的波特率,否则数据会错位。我在项目中遇到过好几次,板子连上电脑没输出,最后发现是波特率设错了——这种低级错误,排查起来最浪费时间。

异步通信的另一个特点是帧结构。每一帧数据包含:

  • 起始位:1位,低电平,告诉接收方“我要开始发了”
  • 数据位:5~9位,通常是8位,就是你要传的字节
  • 校验位:可选,用于简单检错
  • 停止位:1位或2位,高电平,表示这一帧结束

嗯,这里要注意:空闲时TX线保持高电平。起始位拉低,就是给接收方一个明确的“开始”信号。

1.3 起始位/数据位/校验位/停止位详解

咱们一个一个拆开讲。

起始位(Start Bit)

起始位永远是低电平,持续一个位时间。接收方检测到电平从高变低,就知道数据要来了。

我曾经用逻辑分析仪抓过一个UART信号,发现起始位有毛刺——就是电平跳变不干净。结果查出来是板子电源纹波太大,导致TX引脚电平抖动。这种问题,光看代码是看不出来的。

数据位(Data Bits)

数据位是实际传输的内容。常见配置是8位数据位,因为正好对应一个字节。

数据位的顺序是低位在前(LSB first)。比如你要发0x55(二进制01010101),实际线上先发最低位1,再发0,再发1……以此类推。

小技巧:用逻辑分析仪抓UART信号时,如果看到波形是01010101这样交替的,多半是0x55或0xAA。这两个字节常被用来做线路测试。

校验位(Parity Bit)

校验位用于简单的错误检测。有三种模式:

模式 规则 适用场景
无校验(None) 不发送校验位 大多数调试场景
奇校验(Odd) 数据位+校验位中1的个数为奇数 对可靠性有要求时
偶校验(Even) 数据位+校验位中1的个数为偶数 对可靠性有要求时

举个例子:数据位是0x41(二进制01000001),有2个1。如果用偶校验,校验位就是0,因为2已经是偶数了。如果用奇校验,校验位就是1,让总1数变成3(奇数)。

注意:校验位只能检测奇数个错误。如果两个位同时出错,校验位就发现不了。所以它只适合低噪声环境。我在一个工业项目中吃过这个亏——现场电机一启动,通信就乱码,校验位根本没用。后来换了CRC校验才解决。

停止位(Stop Bit)

停止位是高电平,持续1位或2位时间。它给接收方一个缓冲,处理完当前帧再准备接收下一帧。

为什么要有停止位?说白了就是给双方一个喘息的机会。如果连续发数据,没有停止位,接收方可能来不及处理。

我个人习惯用1位停止位,除非对方明确要求2位。1位停止位效率更高,而且大多数现代设备都能处理。

1.4 UART帧结构总览

把上面这些拼起来,就是一帧完整的UART数据:

空闲(高) | 起始位(低) | 数据位(LSB→MSB) | 校验位(可选) | 停止位(高) | 空闲(高)

用逻辑分析仪看,大概长这样:

高电平 ──────┐
             │
             ▼
起始位  ████  (低电平)
数据位  ██░░██░░  (0和1交替)
校验位  ██  (可选)
停止位  ░░░░  (高电平)
高电平 ──────┐

嗯,这个图是手绘风格的,实际波形会更规整。但核心逻辑就是这样。

1.5 常见配置与参数对比

实际项目中,UART配置五花八门。我整理了一个常用配置表:

参数 常见值 说明
波特率 9600, 19200, 38400, 115200 越高越快,但抗干扰能力下降
数据位 8位(最常见) 7位用于ASCII传输
校验位 None(最常见) 调试场景一般不校验
停止位 1位(最常见) 2位用于低速或噪声环境

你可能会问:为什么调试场景不校验?因为调试口主要用来打印日志,偶尔丢一个字符不影响大局。而且加了校验位,帧长度变了,配置起来更麻烦。

1.6 本章知识结构图

下面这张SVG图,把UART协议的核心知识点串起来了。你可以把它当作本章的思维导图。

UART协议知识结构图 UART协议知识结构 UART协议 历史发展 异步通信原理 帧结构 1960s 大型机 1970s UART芯片 1980s PC集成 波特率约定 无时钟线 起始位 数据位 校验位 停止位 核心要点 UART是异步串行协议,靠波特率同步 帧结构:起始位 + 数据位 + 校验位 + 停止位

1.7 实战中的常见问题

讲完理论,咱们聊聊实战中容易踩的坑。

  1. 波特率不匹配:最常见的问题。两边设置不一致,收到的全是乱码。用逻辑分析仪一看,位宽不对,一眼就能看出来。
  2. 电平不匹配:MCU通常是3.3V或5V,但RS-232标准是±12V。直接连会烧芯片。需要电平转换芯片,比如MAX232。
  3. 信号反相:有些设备用RS-232电平,逻辑1是负电压,逻辑0是正电压。和TTL电平正好相反。我刚开始做项目时就被这个坑过——抓到的波形怎么看都不对,后来发现是电平极性反了。
  4. 地线没接:UART是单端信号,需要共地。如果两个设备的地电位不同,通信就会出问题。我曾经调试一个设备,TX和RX都接对了,但就是没数据。最后发现是GND没连。

调试建议:遇到UART通信问题,第一步用逻辑分析仪抓波形。看起始位有没有、数据位对不对、停止位是否完整。波形对了,问题就在软件;波形不对,问题就在硬件。