3. 串口通信基础:串口协议原理、波特率与数据位、Python pyserial库实战、串口数据抓包分析
串口通信,说白了就是嵌入式世界里最古老也最通用的「对话方式」。我刚开始做飞控地面站那会儿,第一件事就是搞定串口——因为不管你是用MAVLink还是自定义协议,最终都得靠这根串口线把数据从飞控板上拽下来。
这一章,咱们就把串口通信的底裤扒干净。从协议原理到Python实战,再到抓包分析,一条龙走完。
3.1 串口协议原理:为什么叫「串」口?
串口通信的全称是「串行通信接口」。所谓串行,就是数据一位一位地按顺序传输,像一列火车一样,一个车厢接一个车厢地通过铁轨。与之对应的是并行通信,一次传8位、16位,但线多、成本高、抗干扰差。
我当年在学校做第一个单片机项目时,用的就是并行LCD屏,那排线密密麻麻的,焊错一根就黑屏。后来换成串口屏,两根线搞定,世界清净了。
串口通信的核心要素就三个:
- 波特率(Baud Rate):每秒传输的符号数,单位是bps。常见的有9600、115200、921600等。
- 数据位(Data Bits):每个数据包包含的实际数据位数,通常是8位,也有7位、9位的情况。
- 停止位(Stop Bits):标志一个数据帧结束的位,常见1位或2位。
再加上可选的校验位(Parity Bit),就构成了一个完整的串口数据帧。
串口数据帧结构(8N1为例):
起始位(1) + 数据位(8) + 校验位(无) + 停止位(1) = 10位/帧
发送一个字节,实际需要传输10位。所以115200波特率下,理论最大字节传输速率是115200/10 = 11520字节/秒。
3.2 波特率与数据位:为什么飞控常用115200?
你可能会问:为什么无人机飞控和地面站之间,默认波特率大多是115200?
原因很简单:平衡。115200在大多数STM32和Pixhawk硬件上,时钟误差小于1%,而且传输速率够用——MAVLink协议一个典型消息包也就几十字节,115200足够每秒传几百条消息。再往上走,比如921600,虽然更快,但对线材和干扰更敏感,我就在项目里吃过这个亏。
我记得有一次调试一款四旋翼,飞控日志里总有随机丢包。查了两天,最后发现是USB转串口线质量太差,921600下误码率飙升。降到115200后,稳如老狗。
| 波特率 | 字节/秒(8N1) | 适用场景 | 注意事项 |
|---|---|---|---|
| 9600 | 960 | 调试、GPS模块 | 慢,但稳定 |
| 57600 | 5760 | 旧版飞控 | 中等速率 |
| 115200 | 11520 | 主流飞控默认 | 推荐首选 |
| 921600 | 92160 | 高速数传、日志下载 | 对线材要求高 |
避坑指南:我曾经遇到过飞控和地面站波特率设置不一致,但双方都能收到数据——只是全是乱码。这种情况在调试时特别容易忽略,因为串口灯还在闪,你以为在通信,其实在「鸡同鸭讲」。所以第一件事永远是:确认波特率一致。
3.3 Python pyserial库实战:从打开串口到收发数据
好了,理论讲完,咱们直接上代码。Python的pyserial库是串口通信的事实标准,几乎所有的地面站软件底层都用它。
先安装:
pip install pyserial
然后,一个最基础的串口收发程序长这样:
import serial
import time
# 打开串口
ser = serial.Serial(
port='COM3', # Windows下是COM口,Linux下是/dev/ttyUSB0或/dev/ttyACM0
baudrate=115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1 # 读取超时,单位秒
)
# 检查是否打开成功
if ser.is_open:
print(f"串口 {ser.port} 已打开,波特率 {ser.baudrate}")
# 发送数据
ser.write(b'Hello, Flight Controller!\n')
# 读取数据
while True:
if ser.in_waiting > 0:
data = ser.readline()
print(f"收到: {data}")
time.sleep(0.01)
这段代码看起来简单,但有几个坑我得提醒你:
- 端口号:Windows下COM口编号可能变来变去,建议用设备管理器确认。Linux下用
ls /dev/tty*查看。 - 超时设置:timeout=0表示非阻塞,readline会立即返回空;timeout=None表示阻塞等待直到读到数据。我一般设0.1秒,既不会卡死,也不会空转。
- 换行符:MAVLink协议是二进制协议,不依赖换行符。但调试时发文本消息,记得加
\n。
3.4 串口数据抓包分析:用逻辑分析仪看「真」数据
写代码是一回事,但有时候你发出去的数据和飞控收到的数据,可能根本不是一回事。这时候就需要抓包分析了。
我个人最常用的工具是逻辑分析仪,便宜点的几十块钱的Saleae克隆版就够用。配合PulseView或Saleae Logic软件,直接看串口线上的电平变化。
抓包步骤:
- 把逻辑分析仪的通道0接到飞控的TX引脚,GND共地。
- 设置采样率,至少4倍于波特率(115200建议用1MHz以上)。
- 触发方式设为下降沿(起始位是低电平)。
- 开始抓取,然后让地面站发一条MAVLink消息。
- 在软件里解码串口协议,设置波特率、数据位、停止位。
你会看到类似这样的波形:
实际抓包波形解读:
空闲时,TX线为高电平(逻辑1)。
起始位:拉低为0,持续1个位时间。
数据位:从LSB(最低有效位)到MSB依次传输。
停止位:拉高为1,持续1个或2个位时间。
如果波形上有毛刺或电平不稳,说明干扰严重,需要检查接地或降低波特率。
我曾经遇到一个诡异问题:地面站发送的MAVLink心跳包,飞控偶尔收不到。用逻辑分析仪一抓,发现TX线上每隔几十个字节就有一个窄脉冲——原来是USB转串口芯片的驱动问题,导致数据帧间隔不稳定。换了个芯片型号,问题解决。
重要提醒:不要完全相信串口调试助手的显示。有些调试助手会过滤掉非打印字符,而MAVLink是二进制协议,很多字节是不可见的。用逻辑分析仪或二进制抓包工具(如RealTerm、Hercule)才能看到完整数据。
3.5 本章知识体系总览
下面这张图,把串口通信的核心知识点串起来了。你可以把它当作一个快速索引,以后遇到串口问题,先看这张图定位问题在哪一层。
嗯,串口通信这块内容,说深不深,说浅不浅。但它是整个地面站通信的基石——你想想看,如果串口这层都搞不定,后面MAVLink协议解析、消息路由、遥测显示,全都是空中楼阁。
我个人建议,学完这一章后,拿一块飞控板或者一个USB转串口模块,亲手跑一遍上面的Python代码,再用逻辑分析仪看一眼波形。只有亲眼看到那串高低电平在示波器上跳动,你才算真正理解了串口。