第4章:UART串口通信协议详解与电平标准
做嵌入式开发,串口是咱们打交道最多的外设之一。说实话,我见过不少工程师,代码写得飞起,但一遇到串口乱码、通信不稳定,就开始抓瞎。根本原因是什么?就是对UART协议本身的理解不够扎实。
这一章,咱们就把UART的底裤扒干净。从波特率、数据位、停止位、校验位这些基础参数,到RS232和TTL电平的区别,我都会结合自己踩过的坑来讲。你想想看,搞懂了这些,后面调试AT指令才能有的放矢。
4.1 UART帧结构——一个字节是怎么传出去的?
UART是异步串行通信,没有时钟线。收发双方靠什么同步?靠约定的波特率,以及帧结构里的起始位和停止位。
一个完整的UART数据帧,长这样:
空闲状态(高电平) → 起始位(低电平) → 数据位(LSB先发) → 校验位(可选) → 停止位(高电平) → 空闲状态(高电平)
我刚开始学的时候,总觉得“LSB先发”这个事无所谓。直到有一次用逻辑分析仪抓波形,发现数据对不上,才意识到:如果你按MSB顺序去解析,整个字节都是反的。
| 字段 | 长度 | 电平 | 说明 |
|---|---|---|---|
| 空闲位 | 无限制 | 高电平(逻辑1) | 总线空闲状态,线路上保持高 |
| 起始位 | 1位 | 低电平(逻辑0) | 通知接收方:数据要来了 |
| 数据位 | 5~9位(常用8位) | 高/低电平 | 先发最低位(LSB),后发最高位(MSB) |
| 校验位 | 0或1位 | 高/低电平 | 奇校验/偶校验/无校验 |
| 停止位 | 1/1.5/2位 | 高电平(逻辑1) | 帧结束标志,给接收方处理时间 |
4.2 波特率——通信的节拍器
波特率,说白了就是每秒传输多少个码元。对于UART来说,一个码元就是一个bit。所以波特率 = 比特率。
常用值:9600、19200、38400、115200、921600。
这里有个关键点:收发双方的波特率误差必须在±2%以内。超过这个范围,就会出现间歇性乱码。
为什么会这样?因为UART接收方是用内部时钟去采样数据线的。假设波特率是9600,每个bit的时长约104μs。接收方会在每个bit的中间位置采样。如果时钟偏差太大,采样点就会偏移,最终采到错误的电平。
4.3 数据位、停止位、校验位——细节决定成败
4.3.1 数据位
常用的是8位数据位。为什么?因为一个字节就是8位,方便。7位数据位在老的ASCII通信中还有,现在很少见了。9位数据位用在一些特殊协议里,比如多机通信的地址帧识别。
我个人建议:除非有特殊需求,一律用8位数据位。少给自己找麻烦。
4.3.2 停止位
停止位不是“停止传输”,而是给接收方一个处理窗口。1位停止位是最常见的。1.5位和2位用在慢速设备或长线传输场景。
你想想看,如果接收方的中断服务函数执行时间比较长,停止位太短,下一帧的起始位就来了,容易造成数据覆盖。所以,如果你的MCU主频不高,或者中断里有复杂处理,用2位停止位更稳妥。
4.3.3 校验位
校验位分三种:无校验(None)、奇校验(Odd)、偶校验(Even)。
校验位只覆盖数据位,不覆盖起始位和停止位。它的原理很简单:
- 偶校验:数据位中1的个数 + 校验位 = 偶数
- 奇校验:数据位中1的个数 + 校验位 = 奇数
但说实话,单bit校验的检错能力非常有限。如果两个bit同时翻转,校验位反而正确。我在实际项目中,如果通信环境比较恶劣(比如电机驱动附近),我会在应用层加CRC校验,而不是依赖UART的硬件校验位。
4.4 RS232 vs TTL电平——别把芯片烧了
这是新手最容易犯的错误。我见过不止一次,有人直接把RS232的DB9接口接到STM32的GPIO上,然后问“为什么芯片冒烟了”。
咱们直接看对比表:
| 项目 | TTL电平 | RS232电平 |
|---|---|---|
| 逻辑1(高电平) | 2.0V ~ 5.0V | -15V ~ -3V |
| 逻辑0(低电平) | 0V ~ 0.8V | +3V ~ +15V |
| 电压摆幅 | 0~5V(或3.3V) | ±12V左右 |
| 传输距离 | 几米以内 | 可达15米以上 |
| 抗干扰能力 | 弱 | 强(差分传输) |
| 常用接口 | 杜邦线、排针 | DB9、端子排 |
看到没?RS232的逻辑1是负电压,逻辑0是正电压。这和TTL正好相反。而且RS232的电压摆幅高达±12V,直接进STM32的GPIO,必烧。
所以,TTL设备和RS232设备通信,必须加电平转换芯片。常用的有MAX232、SP3232等。这些芯片内部有电荷泵,能把TTL的0~5V转换成RS232的±12V。
4.5 知识结构总览
下面这张图,把本章的核心知识点串起来了。你可以把它当成一个快速参考:
4.6 实战中的电平转换方案
最后,我分享一下实际项目中常用的几种电平转换方案:
- STM32 ↔ PC(USB转TTL):直接用CH340或CP2102模块,3.3V供电,TX/RX交叉连接。最简单。
- STM32 ↔ 老式设备(RS232):必须加MAX232或SP3232。注意MAX232需要外接4个电解电容(1μF左右),别漏了。
- STM32 ↔ 长距离传输:用RS485,半双工,差分信号,抗干扰强。但协议要自己处理收发切换。
- 3.3V ↔ 5V TTL互连:如果STM32是3.3V,对方是5V TTL,TX方向可以直接连(3.3V被识别为高),RX方向需要加电阻分压或用电平转换芯片。