一、UART通信协议基础:什么是UART、串口通信原理、波特率、数据位、停止位、校验位

大家好,我是你们的嵌入式讲师。今天咱们来聊聊UART——这个在嵌入式世界里几乎无处不在的通信协议。说实话,我做了十几年嵌入式开发,UART是我用得最多的接口,没有之一。从调试日志到传感器数据读取,从GPS模块到蓝牙模块,几乎每个项目都离不开它。

1.1 什么是UART?

UART的全称是Universal Asynchronous Receiver/Transmitter,中文叫通用异步收发器。说白了,它就是一套让两个设备之间通过两根线就能聊天的硬件电路。

我刚开始学嵌入式时,总觉得UART这个名字很唬人。后来发现,它其实就是个串行通信的翻译官——把设备内部的并行数据转成串行的一比特一比特发出去,再把收到的串行数据转回并行。嗯,就这么简单。

核心要点:UART是硬件协议,不是软件协议。它规定了电气特性、帧格式和时序,但不管数据内容是什么。你发"Hello"还是发0x55,UART一视同仁。

1.2 串口通信原理

串口通信,顾名思义就是数据一位一位地传输。你想想看,如果8位数据同时用8根线传,那就是并行通信;如果只用1根线,按顺序传8次,那就是串行通信。

UART通信需要三根线:TX(发送)、RX(接收)、GND(地线)。两个设备的TX接对方的RX,RX接对方的TX,地线共地。我在项目中遇到过不少新手把TX和TX直接连在一起,结果死活通信不上——嗯,这个坑我当年也踩过。

UART是异步通信,什么意思?就是收发双方没有独立的时钟线。那它们怎么同步呢?靠的是双方约定好的波特率,以及每个数据帧的起始位和停止位。

个人经验:我建议你在调试UART时,先用示波器看看TX脚的波形。一个完整的UART帧看起来就像一串高低电平的脉冲,起始位是低电平,数据位从LSB开始,停止位是高电平。看一眼波形,比读十页文档都管用。

1.3 波特率

波特率(Baud Rate)是UART通信中最关键的参数之一。它表示每秒传输的符号数,单位是bps(bits per second)。常见的波特率有9600、19200、38400、115200等。

为什么说它关键?因为收发双方必须使用相同的波特率,否则收到的数据全是乱码。我曾经调试一个GPS模块,折腾了半天才发现是波特率设成了9600,而模块默认是4800——那数据简直没法看。

波特率 (bps) 每比特时间 (μs) 传输1字节耗时 (ms) 典型应用场景
9600 104.17 约1.04 GPS模块、低速传感器
38400 26.04 约0.26 蓝牙模块、工业设备
115200 8.68 约0.09 调试日志、高速数据传输
921600 1.09 约0.01 树莓派与PC高速通信

这里有个小细节:波特率不等于比特率。在UART中,每个符号就是1个比特,所以两者相等。但在其他调制方式中,一个符号可能携带多个比特,那时波特率和比特率就不一样了。

1.4 数据位

数据位(Data Bits)是每个UART帧中实际传输的数据位数。常见的有5、6、7、8位,最常用的是8位。为什么?因为一个字节正好8位,方便处理ASCII字符和二进制数据。

我记得有一次做项目,需要和一台老旧的工业仪表通信。那仪表只支持7位数据位,我习惯性地设成了8位,结果读回来的数据总是少一位。排查了半天才发现是数据位不匹配——嗯,这种老设备现在不常见了,但遇到了真能让人抓狂。

避坑指南:我曾经在树莓派上用pyserial读取一个传感器模块,数据总是错位。后来发现传感器用的是7位数据位+偶校验,而我默认设成了8位无校验。记住:数据位、校验位、停止位这三者必须完全匹配,缺一不可。

1.5 停止位

停止位(Stop Bits)标志一个UART帧的结束。它可以是1位、1.5位或2位的高电平。最常用的是1位停止位。

为什么需要停止位?说白了就是给接收端一个缓冲时间,让它准备好接收下一个帧。如果停止位太短,接收端可能还没处理完上一个字节,下一个字节就来了,导致数据丢失。

我个人的习惯是:在短距离通信(比如板级通信)中用1位停止位就够了;如果通信距离较长或者环境干扰大,我会用2位停止位,虽然传输效率低一点,但可靠性更高。

1.6 校验位

校验位(Parity Bit)用于简单的错误检测。它分为三种:无校验(None)、奇校验(Odd)、偶校验(Even)。

工作原理很简单:发送端根据数据位中1的个数,自动设置校验位为0或1,使得数据位+校验位中1的总数为奇数(奇校验)或偶数(偶校验)。接收端收到后重新计算,如果发现不一致,就说明传输过程中发生了错误。

说实话,这种校验方式很基础,只能检测奇数个比特的错误。如果两个比特同时翻转,校验位就检测不出来了。但在大多数嵌入式场景中,UART通信距离短、干扰小,这种校验已经够用。

校验方式 校验位值 检测能力 适用场景
无校验 (None) 无 无 调试、短距离可靠通信
奇校验 (Odd) 使1的总数为奇数 检测奇数个比特错误 工业环境、噪声较大
偶校验 (Even) 使1的总数为偶数 检测奇数个比特错误 Modbus协议、标准通信

1.7 UART帧结构总览

把上面这些概念串起来,一个完整的UART帧长这样:

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

举个例子,最常用的配置是8N1:8位数据位、无校验、1位停止位。加上1位起始位,总共10位传输1个字节。所以波特率9600时,每秒大约能传960个字节。

计算公式:实际数据传输速率 = 波特率 / (1 + 数据位数 + 校验位数 + 停止位数)

以9600 8N1为例:9600 / (1 + 8 + 0 + 1) = 960 字节/秒

你想想看,如果换成8E2(8位数据位、偶校验、2位停止位),那每帧就是1+8+1+2=12位,同样9600波特率下只能传800字节/秒。效率低了,但可靠性高了。这就是个取舍问题。

1.8 UART通信知识结构图

下面这张图把UART通信的核心知识点串起来了,方便你建立整体认知:

UART通信协议知识结构图 UART通信协议知识结构 UART通信协议 硬件接口 帧格式 通信参数 TX 发送线 RX 接收线 GND 地线 起始位 (1位) 数据位 (5~8位) 校验位 (0/1位) 停止位 (1/1.5/2位) 波特率 数据位长度 校验方式 停止位长度 核心原则 收发双方必须约定完全相同的通信参数 波特率、数据位、校验位、停止位缺一不可 否则就会出现乱码或通信失败

1.9 小结

这一章我们聊了UART通信协议的基础知识。从硬件接口的三根线,到帧结构的四个组成部分,再到通信参数的三个关键配置——这些东西看似零散,但其实是UART通信的基石。

我个人觉得,理解UART最好的方式就是动手。下一章我们会用树莓派的GPIO引脚,配合pyserial库,真正跑起来一个UART通信的例子。到时候你会发现,这些理论知识全都能用上。

课后小练习:打开你的树莓派终端,输入 ls /dev/tty* 看看有哪些串口设备。找到 /dev/ttyAMA0 或 /dev/ttyS0,这就是树莓派的硬件UART接口。先混个脸熟,后面我们会用它做实验。