1. PySide6 QtSerialPort 串口通信基础
在嵌入式开发和硬件交互领域,串口通信是最基础也最可靠的通信方式之一。PySide6 提供的 QtSerialPort 模块为 Python 开发者提供了完整的跨平台串口通信解决方案。与传统的 pyserial 库相比,QtSerialPort 的最大优势在于其原生集成到 Qt 事件循环中,能够实现真正的异步非阻塞通信。
1.1 串口通信基础概念
串口通信需要通信双方约定好以下核心参数,这些参数必须在代码中正确设置才能建立有效连接:
-
波特率:表示每秒传输的符号数,常见值有 9600、19200、38400、57600、115200 等。波特率越高传输速度越快,但抗干扰能力会下降。对于大多数 Arduino 开发板,默认使用 9600 或 115200。
-
数据位:每个字节包含的数据位数,通常为 5、6、7 或 8 位。现代设备普遍使用 8 位数据位,这是能完整表示一个 ASCII 字符的最小位数。
-
校验位:用于简单的错误检测,可选 None(无校验)、Odd(奇校验)、Even(偶校验)、Mark(强制为1)和 Space(强制为0)。大多数情况下使用无校验。
-
停止位:表示单个数据包结束的位,可以是 1 位、1.5 位或 2 位。现代设备几乎都使用 1 位停止位。
-
流控制:用于防止数据溢出,可选 None(无流控)、Hardware(硬件流控,使用 RTS/CTS 信号线)和 Software(软件流控,使用 XON/XOFF 字符)。简单应用中通常不需要流控。
1.2 QtSerialPort 架构设计
QtSerialPort 采用典型的 Qt 模块化设计,将功能清晰地划分到两个核心类中:
-
QSerialPort:负责实际的串口操作
- 端口配置与开关
- 数据读写
- 状态监控
- 错误处理
-
QSerialPortInfo:提供端口枚举功能
- 获取可用端口列表
- 查询端口详细信息
- 验证端口有效性
这种分离设计使得开发者可以先用 QSerialPortInfo 获取系统信息,再使用 QSerialPort 进行实际操作,代码结构更加清晰。
2. QtSerialPort 核心类详解
2.1 QSerialPort 操作类
2.1.1 端口配置
端口配置是串口通信的第一步,必须确保所有参数与连接的设备完全一致。以下是典型的配置代码:
python复制serial = QSerialPort()
serial.setPortName("COM3") # Windows 格式
# serial.setPortName("/dev/ttyUSB0") # Linux 格式
# 基本参数配置
serial.setBaudRate(QSerialPort.Baud115200)
serial.setDataBits(QSerialPort.Data8)
serial.setParity(QSerialPort.NoParity)
serial.setStopBits(QSerialPort.OneStop)
serial.setFlowControl(QSerialPort.NoFlowControl)
# 高级参数配置(可选)
serial.setReadBufferSize(1024) # 设置接收缓冲区大小
注意:在 Windows 系统上,端口名格式为 "COMx"(x 为数字);在 Linux 系统上则为 "/dev/ttyX" 或 "/dev/ttyUSBX" 格式。跨平台开发时需要特别注意这一点。
2.1.2 数据读写操作
QtSerialPort 提供了多种数据读写方式,最常用的是异步信号槽机制:
python复制# 写入数据(注意必须转换为 bytes)
data = "Hello World".encode('utf-8') # 字符串转字节
bytes_written = serial.write(data)
# 读取数据(通过信号槽)
serial.readyRead.connect(self.handle_ready_read)
def handle_ready_read(self):
data = serial.readAll() # 返回 QByteArray
text = bytes(data).decode('utf-8') # 转换为字符串
print("Received:", text)
对于需要精确控制读取长度的场景,可以使用 read(maxSize) 方法指定要读取的字节数。这在处理固定长度协议时特别有用。
2.1.3 错误处理机制
完善的错误处理是串口通信稳定性的关键。QtSerialPort 通过 errorOccurred 信号报告错误:
python复制serial.errorOccurred.connect(self.handle_error)
def handle_error(self, error):
if error == QSerialPort.NoError:
return
elif error == QSerialPort.DeviceNotFoundError:
print("Error: Device not found")
# 其他错误处理...
serial.close() # 发生错误时建议关闭端口
2.2 QSerialPortInfo 信息类
QSerialPortInfo 提供了丰富的端口信息查询功能,非常适合用于构建用户友好的端口选择界面:
python复制# 获取所有可用端口
ports = QSerialPortInfo.availablePorts()
for port in ports:
print(f"Port: {port.portName()}")
print(f"Description: {port.description()}")
print(f"Manufacturer: {
