3、Python串口编程基础:pySerial库安装、串口参数配置、数据发送与接收基础API
好,咱们进入实战环节。前面聊了那么多UART的理论,现在该动手了。Python做串口通信,绕不开的就是pySerial这个库。我最早用Python调串口是在一个产线测试项目里,当时赶工期,文档也没细看,结果被几个小坑绊得够呛。今天我把这些经验揉碎了讲给你听。
3.1 安装pySerial:别小看这一步
安装本身很简单,一行命令搞定:
pip install pyserial
但有个细节我吃过亏——权限问题。在Linux下,如果你直接用pip装,可能发现程序跑起来报错说打不开串口。为什么?因为当前用户没有dialout组的权限。
我曾经在树莓派上折腾了半小时,最后发现是忘了把用户加到dialout组。执行下面这条命令,然后注销重登就好了:
sudo usermod -a -G dialout $USER
Windows下一般没问题,但注意别装成Python 2的版本。现在都2025年了,用Python 3吧。
3.2 串口参数配置:参数配不对,通信全白费
打开串口前,你得告诉pySerial一堆参数。我习惯把它们写在一个字典里,方便维护:
import serial
config = {
'port': 'COM3', # Windows下是COM口,Linux下是/dev/ttyUSB0之类的
'baudrate': 115200, # 波特率,常见的有9600、19200、115200
'bytesize': serial.EIGHTBITS, # 数据位,通常是8位
'parity': serial.PARITY_NONE, # 校验位,NONE/EVEN/ODD
'stopbits': serial.STOPBITS_ONE, # 停止位,1位或2位
'timeout': 1, # 读超时,单位秒。None表示一直等
'xonxoff': False, # 软件流控,一般关掉
'rtscts': False # 硬件流控,也关掉
}
ser = serial.Serial(**config)
这里有个参数我得重点说说——timeout。我见过不少新手把它设成None,结果程序卡死在read()那里,界面假死。你想想看,如果对端设备突然不发了,你的程序就永远等下去了。
我个人习惯:调试阶段timeout设1秒,正式环境根据最坏情况设3-5秒。这样即使通信异常,程序也能及时报错退出。
3.3 数据发送与接收:核心API实战
pySerial的发送和接收API非常简洁,就几个函数。但简洁不代表简单,用不好照样出问题。
3.3.1 发送数据
# 发送字符串(需要编码成bytes)
ser.write(b'Hello UART\n')
# 发送十六进制数据
ser.write(bytes([0xAA, 0x55, 0x01, 0x02, 0x03]))
# 发送整型变量
data = 0x1234
ser.write(data.to_bytes(2, 'big')) # 大端模式,2字节
注意:write()返回的是实际发送的字节数。我遇到过USB转串口线质量差,明明要发100字节,实际只发了80字节。所以严谨的做法是检查返回值:
sent = ser.write(data)
if sent != len(data):
print(f"警告:只发送了{sent}/{len(data)}字节")
3.3.2 接收数据
接收有几种方式,看场景选:
| 方法 | 说明 | 适用场景 |
|---|---|---|
ser.read(size) |
读取指定字节数,超时返回已读到的数据 | 已知数据帧长度 |
ser.readline() |
读到换行符\n为止 | 文本协议,如AT指令 |
ser.read_until(expected) |
读到指定字节序列为止 | 自定义帧尾,如0x0D0A |
ser.in_waiting |
返回接收缓冲区中的字节数 | 非阻塞轮询 |
我常用的模式是先查in_waiting,再读:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting)
print(f"收到{len(data)}字节: {data.hex()}")
避坑指南:
readline()依赖超时机制。如果对端设备不发送换行符,程序会一直等到timeout。我曾经调试一个GPS模块,死活收不到完整数据,最后发现模块输出的是回车符\r而不是换行符\n。改用read_until(b'\r')就解决了。
3.4 完整示例:一发一收
把上面知识点串起来,写个简单的环回测试:
import serial
import time
ser = serial.Serial(
port='COM3',
baudrate=115200,
timeout=1
)
# 发送测试数据
test_data = bytes([0xAA, 0x55, 0x01, 0x02, 0x03, 0x04, 0x05])
ser.write(test_data)
print(f"发送: {test_data.hex()}")
# 等待并接收回显
time.sleep(0.1) # 给设备一点处理时间
if ser.in_waiting > 0:
rx_data = ser.read(ser.in_waiting)
print(f"接收: {rx_data.hex()}")
# 简单校验
if rx_data == test_data:
print("环回测试通过!")
else:
print("数据不匹配!")
else:
print("未收到数据")
ser.close()
这个例子虽然简单,但已经包含了串口编程的核心流程:打开→配置→发送→接收→校验→关闭。后面的章节我们会在这个基础上不断加码。
3.5 本章知识结构
下面这张图把pySerial的核心脉络理清楚了,你可以对照着回顾: