Python使用pyserial库实现串口数据读写基础教程
在单片机调试、工控设备通信以及各种硬件交互场景中,串口通信(UART/RS-232/RS-485)是最为基础且可靠的通讯方式。Python通过官方维护的第三方库 pyserial,提供了对物理串口、USB转串口芯片的底层控制接口。本文将从安装准备入手,完整演示如何通过 Python 实现串口的打开、参数配置、文本及十六进制字节收发,以及异常处理机制。
一、串口通信机制与通讯架构
串口通信是一种点对点传输协议,数据按照位(bit)在单根发送线(TX)和接收线(RX)上串行流动。计算机通常通过 USB 转串芯片(如 CH340、CP2102、FT232)生成虚拟串口与外设交互。进行有效通信的前提是两端协商好通信参数:波特率(Baudrate)、数据位(Data bits)、停止位(Stop bits)和校验位(Parity)。
二、环境准备与包安装
在 Python 环境中,通过 pip 工具安装包时需注意包名称是 pyserial,而不是 serial。如果在系统中错误安装了名为 serial 的同名废弃包,会导致接口混乱无法导入。
打开终端或命令行窗口,执行以下命令安装:
pip install pyserial
pip install serial,请先运行 pip uninstall serial,随后重新执行 pip install pyserial。在代码中导入时统一使用 import serial。
三、核心操作实施流程
使用 pyserial 进行串口通讯遵循标准且严格的生命周期:从扫描端口开始,建立连接配置参数,经由数据编码发送与解码接收,并在操作结束时妥善关闭端口释放系统资源。
步骤 1:扫描当前系统可用的串口
在尝试连接前,首先确认系统分配给硬件的具体串口号。不同系统的端口命名规则不同:Windows 下表现为 COM1、COM3 等;Linux 和 macOS 则为 /dev/ttyUSB0 或 /dev/tty.usbserial-*。
import serial.tools.list_ports
ports = serial.tools.list_ports.comports()
if not ports:
print("未发现可用串口设备")
else:
for port, desc, hwid in ports:
print(f"端口: {port} | 描述: {desc} | 硬件标识: {hwid}")
步骤 2:打开串口并配置核心参数
通过实例化 serial.Serial 对象建立连接。核心配置必须与对端硬件约定完全一致:
port:串口名称,如"COM3"。baudrate:波特率,常用值为9600、115200。bytesize:数据位,默认为 8 位(serial.EIGHTBITS)。parity:校验位,默认为无校验(serial.PARITY_NONE)。stopbits:停止位,默认为 1 位(serial.STOPBITS_ONE)。timeout:读操作超时时间(秒)。如果不设置,程序在未接收到足量数据前将一直阻塞挂起。
四、数据类型与读写核心差异
初学者在使用 pyserial 时最容易遇到的问题是编码类型报错。pyserial 的底层输入输出完全基于 bytes(字节串)对象,不支持直接传递 Python 原生字符串(str)。无论是文本数据还是十六进制命令,都需要在通信层进行恰当的转换。
五、完整代码示例:安全读写与上下文管理
推荐使用 Python 的 with 语句管理串口实例,这样即使程序抛出异常,Python 也会确保在退出上下文时自动调用 ser.close(),避免端口被后台进程长期占用导致下次无法打开。
import time
import serial
# 配置串口参数
PORT_NAME = "COM3"
BAUD_RATE = 115200
try:
with serial.Serial(port=PORT_NAME, baudrate=BAUD_RATE, timeout=1.0) as ser:
print(f"成功打开串口: {ser.name}")
# 很多开发板(如 Arduino)在打开串口时会发生复位,建议保留短暂延时
time.sleep(2)
# 1. 发送文本命令(需要转换为字节,并根据协议添加换行符)
cmd = "STATUS\r\n"
ser.write(cmd.encode("utf-8"))
print(f"已发送指令: {cmd.strip()}")
# 2. 读取一行返回数据
# readline 会一直读取,直到遇到 \n 或达到设定的 timeout 限制
response_bytes = ser.readline()
if response_bytes:
response_text = response_bytes.decode("utf-8", errors="replace").strip()
print(f"收到文本响应: {response_text}")
else:
print("读取超时,未接收到有效响应")
# 3. 发送十六进制命令帧(例如读取传感器数据)
hex_cmd = bytes.fromhex("01 03 00 00 00 02 C4 0B")
ser.write(hex_cmd)
# 读取指定长度(8字节)的响应
hex_resp = ser.read(8)
if hex_resp:
print(f"收到十六进制响应: {hex_resp.hex(' ').upper()}")
except serial.SerialException as e:
print(f"串口通信发生错误: {e}")
六、排查检查清单与注意事项
在开发过程中,若通信未能达到预期,可以依据下述决策检查表逐项确认硬件和软件的状态配置:
掌握了上述的端口扫描、连接参数匹配、字节编解码与异常处理方法,便可建立起稳定的串口通信基础。在应对复杂协议或高频数据采集时,可在此基础上进一步结合多线程或异步队列来分离数据读取与业务解析逻辑。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









