1. UART基础与双工通信原理

各位同学好,我是老周。做嵌入式这行十几年了,UART 可以说是我打交道最多的外设之一。今天咱们就从最基础的东西聊起——UART 协议帧格式、波特率怎么算、全双工和半双工到底差在哪,还有那个让人又爱又恨的 RS232 电平标准。

嗯,这部分内容看似简单,但很多坑都藏在这些基础里。我见过不少工程师,上来就调中断、写 DMA,结果收发数据总是不对,回头一查——波特率算错了,或者电平不匹配。所以,咱们先把地基打牢。

1.1 UART 协议帧格式

UART 全称是 Universal Asynchronous Receiver/Transmitter,通用异步收发器。说白了,它就是一种串行通信协议,一根线发数据,一根线收数据,不需要时钟线。

那它怎么保证收发双方节奏一致呢?靠的是帧格式和波特率。

一个标准的 UART 数据帧长这样:

起始位(1bit) + 数据位(5~8bit) + 校验位(0/1bit) + 停止位(1/1.5/2bit)

我刚开始学的时候,总觉得这结构有点啰嗦。后来在项目里吃过亏才明白——每一段都有它的用处。

字段 长度 说明
起始位 1 bit 拉低电平,告诉接收方"我要发数据了"
数据位 5~8 bit 实际传输的数据,常用 8 位
校验位 0 或 1 bit 奇校验或偶校验,用于检错
停止位 1/1.5/2 bit 拉高电平,表示帧结束
我的习惯: 做通用驱动时,我一般固定用 8 位数据位、无校验、1 位停止位——也就是常说的 8N1。兼容性最好,大部分 MCU 和传感器都支持。

1.2 波特率计算

波特率就是每秒传输的比特数,单位是 bps。比如 115200 bps,意思是一秒传 115200 个 bit。

你想想看,如果发送方和接收方的波特率没对齐,那收出来的数据全是乱的。我在一个项目里就遇到过——用 9600 的波特率去收 19200 发出来的数据,结果全是乱码,排查了半天才发现是配置写错了。

波特率的计算公式:

波特率 = 时钟频率 / (16 × 分频系数)

以 STM32 为例,假设时钟频率是 72 MHz,想要 115200 bps:

分频系数 = 72000000 / (16 × 115200) ≈ 39.0625
取整后:USARTDIV = 39

实际波特率 = 72000000 / (16 × 39) ≈ 115384 bps,误差约 0.16%,完全可用。

注意: 波特率误差超过 2% 就可能丢数据。我曾经在 8 MHz 晶振下配 250000 bps,误差到了 3.5%,结果通信时好时坏,折腾了两天才发现是晶振频率不合适。

1.3 全双工与半双工

这两个概念其实不难理解。

  • 全双工: 发送和接收可以同时进行。UART 就是全双工——TX 只管发,RX 只管收,互不干扰。
  • 半双工: 同一时刻只能发或只能收。比如 RS485 就是半双工,收发共用一对线,靠方向控制切换。

我刚开始做项目时,总觉得全双工肯定比半双工好。后来发现不是这么回事——全双工需要两根线,半双工只需要一根(或一对),在长距离布线时,半双工的成本优势很明显。

特性 全双工 半双工
通信方向 同时双向 分时双向
线数需求 2 根(TX/RX) 1 根(或一对差分线)
典型协议 UART、SPI RS485、I²C
适用场景 短距离、高速交互 长距离、多节点组网

1.4 RS232 电平标准

很多初学者会混淆 UART 逻辑电平和 RS232 电平。UART 芯片出来的信号是 TTL 电平——0V 表示逻辑 0,3.3V 或 5V 表示逻辑 1。但 RS232 标准不一样:

  • 逻辑 0:+3V ~ +15V
  • 逻辑 1:-3V ~ -15V

为什么会这样?说白了,RS232 用正负电压是为了抗干扰。电压摆幅大,噪声容限就高,适合长距离传输。但代价是——不能直接和 MCU 的 UART 引脚相连,必须加电平转换芯片,比如 MAX232。

关键点: MCU 的 UART 引脚输出的是 TTL 电平,接 RS232 设备时必须加电平转换。我见过有人直接把 3.3V 的 TX 接到 RS232 的 RX 上,结果烧了接口芯片——电平不匹配,轻则通信失败,重则烧硬件。

下面这张图展示了 UART 通信的完整链路:

UART 双工通信链路示意图 发送端 MCU UART TX / RX 电平转换 TTL ↔ RS232 电平转换 RS232 ↔ TTL 接收端 MCU UART RX / TX TX 路径 RX 路径 说明:MCU 输出 TTL 电平,经 MAX232 等芯片转换为 RS232 电平 RS232 使用 ±12V 信号,抗干扰能力强,适合 15 米以内通信 典型 UART 帧波形(8N1) 起始 8 位数据位 (D0~D7) 停止
经验之谈: 做调试时,我习惯先用示波器看 TX 引脚的波形。确认起始位、数据位、停止位都正常,再查波特率。这样能快速定位问题是出在硬件还是软件。