尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Qt 开发实战:从零打造一个跨平台串口调试助手

Qt 开发实战:从零打造一个跨平台串口调试助手
📅 发布时间:2026/7/1 18:03:33

1. 引言

串口通信在嵌入式、物联网、工业自动化等领域应用广泛。虽然市面上已有成熟的串口调试工具(如 SSCOM、Putty 等),但自己动手用 Qt 开发一个,既能深入理解串口通信原理,又能按需定制功能,还能积累宝贵的项目经验。

本文带你从零开始,使用 Qt6 + C++ 开发一个具备串口扫描、参数配置、数据收发、十六进制支持、日志保存等功能的轻量级串口调试助手,并在虚拟串口环境下完成联调测试。

2. 开发环境

  • 操作系统:Windows 10 / 11(也支持 Linux / macOS)

  • 开发工具:Qt Creator 13.0.2

  • Qt 版本:Qt 6.7.2 / 6.8.0(支持 Qt 5.15+)

  • 构建系统:CMake(也可用 qmake)

  • 编译器:MinGW 13.1.0 / MSVC 2022

  • 额外工具:LLCOM(串口调试助手,用于联调)、com0com(虚拟串口驱动,用于无硬件测试)

3. 项目结构

text

serial-assistant/ ├── CMakeLists.txt ├── main.cpp ├── mainwindow.h ├── mainwindow.cpp ├── mainwindow.ui ├── resources.qrc └── style/ └── style.qss
  • CMakeLists.txt:项目构建配置,需添加SerialPort组件。

  • main.cpp:程序入口,加载样式表。

  • mainwindow.h / .cpp:主窗口逻辑,串口操作核心。

  • mainwindow.ui:UI 布局,含按钮、下拉框、文本编辑区等。

  • resources.qrc:资源文件,打包样式表。

  • style/style.qss:QSS 样式表(可选,用于美化界面)。

4. 功能列表

  • ✅ 自动扫描并显示可用串口

  • ✅ 配置波特率(9600~115200)

  • ✅ 打开/关闭串口(带状态提示)

  • ✅ 异步接收数据(文本 / HEX 两种显示模式)

  • ✅ 发送数据(文本 / HEX 两种模式)

  • ✅ 清空接收区

  • ✅ 保存接收数据到.txt文件

  • ✅ 状态栏显示收发字节数

  • ✅ QSS 美化界面(可选)

5. 核心实现步骤

5.1 CMake 配置(添加 SerialPort 模块)

cmake

# CMakeLists.txt 片段 find_package(Qt6 REQUIRED COMPONENTS Core Widgets SerialPort) target_link_libraries(serial-assistant PRIVATE Qt6::Core Qt6::Widgets Qt6::SerialPort )

5.2 扫描串口并填充下拉框

在MainWindow构造函数中:

cpp

foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { ui->comboBoxPort->addItem(info.portName()); }

5.3 打开/关闭串口

cpp

void MainWindow::on_pushButtonOpen_clicked() { if (serial->isOpen()) { serial->close(); ui->pushButtonOpen->setText("打开串口"); ui->comboBoxPort->setEnabled(true); ui->comboBoxBaud->setEnabled(true); statusBar()->showMessage("串口已关闭", 2000); return; } QString portName = ui->comboBoxPort->currentText(); qint32 baudRate = ui->comboBoxBaud->currentText().toInt(); serial->setPortName(portName); serial->setBaudRate(baudRate); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); if (serial->open(QIODevice::ReadWrite)) { ui->pushButtonOpen->setText("关闭串口"); ui->comboBoxPort->setEnabled(false); ui->comboBoxBaud->setEnabled(false); connect(serial, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead); statusBar()->showMessage(QString("已打开 %1 %2").arg(portName).arg(baudRate), 3000); } else { QMessageBox::critical(this, "错误", "打开串口失败:" + serial->errorString()); } }

5.4 接收数据(文本 / HEX 切换)

cpp

void MainWindow::handleReadyRead() { QByteArray data = serial->readAll(); if (data.isEmpty()) return; if (ui->checkBoxHexDisplay->isChecked()) { QString hex = data.toHex(' ').toUpper(); ui->textEditReceive->appendPlainText(hex); } else { QString text = QString::fromUtf8(data); ui->textEditReceive->appendPlainText(text); } }

5.5 发送数据(文本 / HEX 切换)

cpp

void MainWindow::on_pushButtonSend_clicked() { if (!serial->isOpen()) { QMessageBox::warning(this, "提示", "请先打开串口"); return; } QString input = ui->lineEditSend->text(); if (input.isEmpty()) return; QByteArray data; if (ui->checkBoxHexSend->isChecked()) { QString hex = input; hex.remove(' '); hex.remove(','); data = QByteArray::fromHex(hex.toUtf8()); if (data.isEmpty()) { QMessageBox::warning(this, "警告", "无效的十六进制格式"); return; } } else { data = input.toUtf8(); } qint64 written = serial->write(data); if (written == -1) { QMessageBox::critical(this, "错误", "发送失败:" + serial->errorString()); } else { statusBar()->showMessage(QString("发送 %1 字节").arg(written), 2000); } }

5.6 清空接收区

cpp

void MainWindow::on_pushButtonClear_clicked() { ui->textEditReceive->clear(); }

5.7 保存接收数据

cpp

void MainWindow::on_pushButtonSave_clicked() { QString content = ui->textEditReceive->toPlainText(); if (content.isEmpty()) { QMessageBox::information(this, "提示", "接收区为空"); return; } QString fileName = QFileDialog::getSaveFileName(this, "保存接收数据", QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss") + ".txt", "文本文件 (*.txt)"); if (fileName.isEmpty()) return; QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&file); out << content; file.close(); statusBar()->showMessage("数据已保存", 3000); } else { QMessageBox::critical(this, "错误", "无法写入文件:" + file.errorString()); } }

5.8 QSS 全局样式(可选)

在resources.qrc中添加style/style.qss,然后在main.cpp中加载:

cpp

int main(int argc, char *argv[]) { QApplication a(argc, argv); QFile file(":/style/style.qss"); if (file.open(QFile::ReadOnly)) { QString style = QTextStream(&file).readAll(); a.setStyleSheet(style); file.close(); } MainWindow w; w.show(); return a.exec(); }

样式表示例(style.qss):

css

QMainWindow { background-color: #f5f5f5; } QPushButton { background-color: #5c9eff; color: white; border: none; border-radius: 6px; padding: 8px 16px; font-weight: bold; } QPushButton:hover { background-color: #3a7bd5; } QPushButton:pressed { background-color: #2c5fa3; } QComboBox, QLineEdit, QPlainTextEdit { border: 1px solid #ccc; border-radius: 4px; padding: 4px 6px; background-color: white; } QPlainTextEdit, QLineEdit { font-family: Consolas, monospace; font-size: 11px; }

6. 测试验证

6.1 虚拟串口环境搭建

使用com0com创建一对虚拟串口(如 COM5 ↔ COM6),然后用LLCOM(开源的 Lua 脚本串口工具)作为对端。

  • 打开 com0com 的setupc命令行,执行:

    text

    install PortName=COM5 PortName=COM6
  • 在设备管理器中确认 COM5、COM6 已出现(无黄色感叹号)。

6.2 联调测试步骤

  1. 启动 Qt 程序,选择COM5,波特率 115200,点击“打开”。

  2. 启动 LLCOM,选择COM6,相同波特率,点击“打开”。

  3. 在 Qt 发送区输入Hello,点击发送 → LLCOM 接收区应显示Hello。

  4. 在 LLCOM 发送区输入World→ Qt 接收区应显示World。

  5. 勾选 Qt 的“十六进制发送”,输入01 02 03 FF发送 → LLCOM 勾选 HEX 显示,应看到相同内容。

  6. 点击“清空接收区” → 内容清空。

  7. 点击“保存接收区” → 弹出保存对话框,保存为.txt文件,打开查看内容正确。

7. 运行效果截图

​

8. 常见问题与解决方案

问题解决方法
打开串口失败(权限错误)Windows:以管理员身份运行;Linux:将用户加入dialout组
接收区显示乱码检查波特率、数据位等参数是否匹配;尝试 HEX 显示模式
虚拟串口驱动安装失败使用com0com 2.2.2.0版本,或禁用驱动签名(临时)
打包发布后缺少 DLL使用windeployqt工具自动复制依赖库

9. 后续拓展方向

  • 多线程接收:将串口读取移到子线程,防止界面卡顿(适合大数据量场景)。

  • 波形显示:集成Qt Charts,将传感器数值实时绘制曲线。

  • 定时自动发送:增加QTimer,周期性发送预设指令。

  • 协议解析:支持 Modbus RTU、自定义帧头帧尾过滤。

  • 配置文件保存:用QSettings记住最近使用的串口号和波特率。

10. 项目总结

通过本项目,你不仅掌握 Qt 串口通信的完整开发流程,还熟悉了 CMake 管理项目、QSS 美化界面、资源文件使用、虚拟串口调试等实用技能。整个项目代码清晰、可扩展性强,可作为毕业设计、简历项目或日常开发工具。

**技术栈**:C++17 / Qt6 / QSerialPort / CMake / QSS

相关新闻

  • Grok在法律场景的真实能力边界与人机协作实践
  • Xshell连接虚拟机——SSH远程连接入门实践报告
  • 深入解析核心组件:企业级USB隔离架构的安全体系与日志API开发实战指南

最新新闻

  • 如何快速上手 openEuler sync-bot:5分钟完成分支同步配置指南
  • gcc-for-openEuler与原生GCC对比:10个关键差异点分析
  • gcc-for-openEuler多架构支持详解:ARM64与x86_64的构建差异
  • OECP内核KABI检测指南:深度解析内核接口兼容性验证
  • 终极内存优化:Mem Reduct实现Windows系统高效管理全攻略
  • LV30条码扫描器与PIC24微控制器的工业级应用方案

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号