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 | 拉高电平,表示帧结束 |
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%,完全可用。
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。
下面这张图展示了 UART 通信的完整链路: