在Linux操作系统下,基于Qt框架进行串口通信开发是嵌入式应用、设备交互等场景中的常见需求,Qt作为跨平台C++ GUI框架,提供了完善的串口通信模块,结合Linux系统的设备文件机制,能够高效实现串口数据的收发与控制,本文将从基础概念、环境搭建、核心类使用、代码实现及常见问题等方面,详细解析Linux下Qt串口通信的开发流程。

Linux串口通信基础概念
Linux系统中,串口设备被抽象为特殊的设备文件,通常位于/dev目录下,如/dev/ttyS0(板载串口)、/dev/ttyUSB0(USB转串口设备)等,串口通信的核心参数包括波特率(Baud Rate)、数据位(Data Bits)、停止位(Stop Bits)、校验位(Parity)和流控制(Flow Control),这些参数需在通信两端保持一致才能正常数据交换。
Qt从5.0版本开始将串口通信模块(Qt Serial Port)纳入标准库,通过QSerialPort和QSerialPortInfo类提供了跨平台的串口操作接口,开发者无需关心底层系统差异,即可实现串口的配置、打开、关闭及数据读写。
开发环境搭建
在Linux系统下进行Qt串口开发,需确保已安装Qt开发环境和串口相关依赖,以Ubuntu系统为例:
-
安装Qt开发环境
通过包管理器安装Qt5,包含核心模块和串口模块:sudo apt-get update sudo apt-get install qt5-default qtserialport5-dev
-
验证串口设备
连接串口设备后,使用ls /dev/tty*命令查看可用串口,dmesg | grep tty可查看设备识别日志,普通用户可能需要配置权限(如加入dialout用户组)才能访问串口设备:sudo usermod -aG dialout $USER
-
创建Qt项目
使用Qt Creator新建”Qt Widgets Application”项目,在.pro文件中添加串口模块引用:QT += serialport
Qt串口核心类解析
QSerialPortInfo类:串口信息获取
QSerialPortInfo用于系统中可用串口的枚举与信息查询,常用方法包括:

static QList<QSerialPortInfo> availablePorts():获取所有可用串口列表。QString portName():获取串口设备名(如/dev/ttyUSB0)。QString description():获取串口描述信息(如”USB Serial Device”)。QString manufacturer():获取设备制造商信息。
通过遍历availablePorts(),可动态填充UI中的串口选择下拉框,提升用户体验。
QSerialPort类:串口操作核心
QSerialPort是串口通信的核心类,负责串口的配置与数据收发,常用功能如下:
-
串口配置
通过setBaudRate()设置波特率(如QSerialPort::Baud9600),setDataBits()设置数据位(如QSerialPort::Data8),setStopBits()设置停止位(如QSerialPort::OneStop),setParity()设置校验位(如QSerialPort::NoParity),setFlowControl()设置流控制(如QSerialPort::NoFlowControl)。 -
串口打开与关闭
open(QIODevice::ReadWrite)以读写模式打开串口,返回bool表示是否成功;close()关闭串口。 -
数据收发
- 写入数据:
write(const QByteArray &data)返回写入字节数,可通过bytesWritten()信号监听写入完成。 - 读取数据:
readAll()读取缓冲区所有数据,read(char *data, qint64 maxSize)读取指定长度数据;readyRead()信号在串口有数据到达时触发,是异步读取的关键。
- 写入数据:
-
错误处理
error()返回当前错误类型,errorString()返回错误描述信息,可用于调试和异常处理。
串口通信代码实现示例
以下实现一个简单的串口助手界面,包含串口选择、打开/关闭、数据发送与接收功能:

UI界面设计(MainWindow.ui)
使用Qt Designer设计界面,包含:
- QComboBox(
cmbPort):选择串口。 - QPushButton(
btnOpenClose):打开/关闭串口。 - QLineEdit(
txtSend):发送数据输入框。 - QPushButton(
btnSend):发送按钮。 - QTextEdit(
txtReceive):接收数据显示框。
核心代码实现(mainwindow.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPortInfo>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// 初始化串口信息
updatePortList();
// 连接信号槽
connect(ui->btnOpenClose, &QPushButton::clicked, this, &MainWindow::togglePort);
connect(ui->btnSend, &QPushButton::clicked, this, &MainWindow::sendData);
connect(&serial, &QSerialPort::readyRead, this, &MainWindow::readData);
}
MainWindow::~MainWindow() {
if (serial.isOpen()) serial.close();
delete ui;
}
// 更新可用串口列表
void MainWindow::updatePortList() {
ui->cmbPort->clear();
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
ui->cmbPort->addItem(info.portName(), info.portName());
}
}
// 打开/关闭串口
void MainWindow::togglePort() {
if (serial.isOpen()) {
serial.close();
ui->btnOpenClose->setText("打开串口");
ui->txtReceive->append("串口已关闭");
} else {
serial.setPortName(ui->cmbPort->currentData().toString());
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setStopBits(QSerialPort::OneStop);
serial.setParity(QSerialPort::NoParity);
serial.setFlowControl(QSerialPort::NoFlowControl);
if (serial.open(QIODevice::ReadWrite)) {
ui->btnOpenClose->setText("关闭串口");
ui->txtReceive->append("串口已打开: " + serial.portName());
} else {
ui->txtReceive->append("打开串口失败: " + serial.errorString());
}
}
}
// 发送数据
void MainWindow::sendData() {
if (!serial.isOpen()) return;
QString data = ui->txtSend->text();
if (data.isEmpty()) return;
serial.write(data.toUtf8());
ui->txtReceive->append("发送: " + data);
}
// 接收数据
void MainWindow::readData() {
QByteArray data = serial.readAll();
ui->txtReceive->append("接收: " + QString(data));
}
关键逻辑说明
- 串口选择:通过
QSerialPortInfo::availablePorts()动态获取系统串口,填充下拉框。 - 异步接收:
readyRead信号触发时调用readData,实时读取串口缓冲区数据并显示。 - 错误处理:串口打开失败时,通过
errorString()输出错误信息,便于调试。
常见问题与解决方案
-
权限问题
现象:普通用户无法打开串口设备,提示”Permission denied”。
解决:将用户加入dialout组(sudo usermod -aG dialout $USER),或修改设备权限(sudo chmod 666 /dev/ttyUSB0)。 -
串口被占用
现象:打开串口时提示”Resource busy”。
解决:检查是否有其他程序占用串口(如lsof /dev/ttyUSB0),关闭占用进程或更换串口号。 -
数据收发乱码
现象:接收或发送的数据出现乱码。
解决:检查通信两端串口参数(波特率、数据位等)是否一致;若存在高电平干扰,可添加滤波电路或软件校验(如CRC校验)。 -
数据丢失
现象:高速数据收发时出现丢包。
解决:使用waitForReadyRead()设置超时读取,或采用多线程分离收发逻辑,避免主线程阻塞。
Linux下基于Qt的串口通信开发,结合了Qt的跨平台优势与Linux设备文件机制,通过QSerialPort和QSerialPortInfo类可高效实现串口配置与数据交互,开发者需掌握串口参数配置、信号槽机制及异步数据处理方法,同时注意权限、占用、乱码等常见问题,本文提供的示例代码可直接作为基础框架,扩展后可应用于工业控制、物联网设备通信等多种场景。

















