当前位置: 首页 > news >正文

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

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

http://www.jsqmd.com/news/1103902/

相关文章:

  • 16 亿美元去哪了?我们追踪了一个 TRON 资金盘的完整链上资金网络
  • 2026年如何选择靠谱的品牌设计执行公司?
  • Grok在法律场景的真实能力边界与人机协作实践
  • Xshell连接虚拟机——SSH远程连接入门实践报告
  • 3分钟掌握LinkSwift:告别网盘限速,解锁全平台高速下载的终极指南
  • 开发一个AI Agent 难不难?提示词工程、上下文记忆、任务编排
  • 深入解析核心组件:企业级USB隔离架构的安全体系与日志API开发实战指南
  • DDR电源网络片上去耦电容模型解析与应用
  • 鸿蒙物理 108 篇 第五十五篇 四象互相生克转化
  • 买二手电脑怕被坑?用鲁大师做这5项检查,卖家都不敢糊弄你
  • 百考通让论文回归有血有肉的人类表达
  • 如何为服务器设计高密度DDR4内存模组?K4AAG165WC-BCWE的16Gb容量与低功耗方案解析
  • 陀螺匠底层架构:轻量化插件底座,支持低代码快速搭建、灵活二开专属业务应用
  • AI编程 - OpenCode+OpenSpec 实战:AI 编程完整演示教程
  • Android SSL证书绕过实战:Xposed模块配置与抓包环境搭建
  • 【会议征稿通知 | 西安理工大学主办 | ACM出版 | EI 、Scopus稳定检索】2026年深度学习与自动化国际学术会议 (ICDLA 2026)
  • CCF-GESP计算机学会等级考试2026年6月三级C++T2 字符转换
  • 专治电力高清显示与开发难题
  • HarmonyOS APP《画伴梦工厂》开发第17篇:视频导出与本地保存——DocumentViewPicker
  • DevSecOps 视角下语音钓鱼(Vishing)通信安全全链路防护研究
  • 2026年国产数据库客户成功案例对比选型
  • 2026年门店小程序平台哪个好?预约、核销和会员储值功能对比
  • 这份榜单够用!2026年好用AI论文工具榜单,免费版也能写合规初稿
  • 系统规划与管理师-信息论与控制论考点解析及应用实践
  • 3PEAK思瑞浦 TPA132A2-TS1R-S TSSOP8 电流信号检测放大器
  • 海外达人营销项目表怎么设计?字段、状态和复盘口径
  • 网易云音乐无损下载器:打造个人专属音乐库的终极方案
  • 深圳猎头公司做GEO,哪家能让AI在招聘推荐里带上自己?
  • Go Eino 框架:从小白到上线,手把手搭建自己的ai模型,基础教学
  • ChanlunX缠论插件:5分钟告别手工画图,开启智能分析新时代 [特殊字符]