Qt 串口调试入门-1:从端口枚举到收发、计数与状态管理
Qt 串口调试入门-1:从端口枚举到收发、计数与状态管理

Qt 串口调试入门:从端口枚举到收发、计数与状态管理

第一次汇报学习笔记:把“能用”的串口收发做扎实——端口枚举、打开关闭、参数锁定、收发计数、暂停显示、接收保存。

做串口工具时,最容易掉进两个坑:串口参数一团乱(打开后还能改参数,导致状态不一致)和收发逻辑混在 UI 里(改一个小功能牵一发动全身)。这篇记录我在 Qt(QSerialPort)里,把串口“基础能力”搭稳的过程。


1. 串口端口枚举:既要“刷新”,也要“别抖”

Qt 提供 QSerialPortInfo::availablePorts() 获取当前系统所有可用串口。最直观的做法是每次刷新就 clear()addItems(),但这样会带来两个体验问题:

  1. 下拉框闪动:列表一刷新就跳回第一项;

  2. 用户选择丢失:原来选的 COM 口不见了。

更好的策略是:

  • 先记录旧的端口名(例如把“COM3: xxx”按冒号切开);

  • 构造新列表;

  • 如果新列表与上次一致就不更新 UI

  • 更新后尝试恢复旧选择,恢复失败再退化到第一项。

另外,很多场景下串口会动态出现/消失(插拔 USB 转串口、创建虚拟串口),所以我会做“自动刷新”。常见做法是 QTimer 每秒刷新一次,并且在用户点开下拉框时再做一次“立即刷新”(后面第 3 篇会写到 eventFilter)。


2. 打开/关闭串口:把参数设置做成“原子操作”

串口打开流程建议按“验证 → 设置 → open → 锁 UI”组织:

  1. 验证是否有端口:下拉框为空就先刷新一次;仍为空则提示;

  2. 解析端口名:不要直接用整个下拉框文本,避免把描述带进去;

  3. 设置波特率/数据位/校验位/停止位

  4. open(QIODevice::ReadWrite)

  5. 打开成功后禁用参数控件(端口、波特率等),避免打开后还改参数导致“看起来改了但实际没生效”。

关闭串口时则反过来:

  • close()

  • 恢复参数控件可编辑;

  • 停止依赖串口的功能(比如定时发送、文件发送、协议组帧等待等);

  • 把“停止显示”这类状态也复位,避免下次打开串口 UI 处在奇怪状态。

这个思路的核心是:打开/关闭串口不仅是 I/O 行为,也是 UI 状态机的一次切换。把它当成事务去处理,后续扩展会轻松很多。


3. readyRead 接收:一次 readAll 不等于“一帧”,但计数要一致

readyRead 信号触发后,最常见代码是:

QByteArray buf = serial.readAll();

这里要注意:串口是字节流,readAll() 取的是“当前缓冲区已有的字节”,不保证是协议意义上的完整帧。即便如此,在“通用串口调试助手”的视角里,把一次 readAll 当成一帧用于统计是可接受的(至少统计口径一致、实现简单)。

因此可以做两套计数:

  • 字节数recvBytes += buf.size()

  • 帧数recvFrames += 1(以一次 readAll 为单位);

并同步更新界面以及状态栏的 S/R 字节显示。


4. “停止显示”与“保存接收”:让数据通路分层

接收数据通常会做三件事:

  1. 计数;

  2. 显示到接收框;

  3. 保存到文件。

如果把“停止显示”做成简单的 return,会导致:用户暂停显示后连保存也停了。更合理的结构是把通路分成两层:

  • 底层通路:计数、保存、协议处理(不受暂停/过滤影响);

  • 展示通路:仅负责把数据渲染到文本框(受暂停/过滤影响)。

这样“停止显示”只影响展示,不影响计数与保存。

保存接收数据我倾向于保存原始字节(QFile::write(buf)),而不是保存“显示字符串”。原因是:显示字符串可能是 HEX 格式、带空格、带时间戳甚至带 TX/RX 前缀;保存原始字节更利于后处理(例如用脚本解析)。


5. 自动清屏:性能优化要提前做

QPlainTextEdit 长期追加文本会越来越卡,尤其是日志量大时。常见处理:

  • 提供“自动清屏”选项;

  • document()->characterCount() 超过阈值(例如 20000)就清空;

  • 清空后重置一些“对齐显示/表头”的内部状态(第 4 篇会详细说)。

这属于“早做早省心”的优化:一开始数据少不明显,但工具一旦上强度(比如持续跑一小时)就会暴露。


6. 小结

这一阶段我最大的收获是:别急着做高级功能,先把串口与 UI 状态机捋清楚。端口刷新不抖、打开关闭原子化、接收通路分层、计数口径一致——这些看起来“很基础”的东西,会决定后续加功能时到底是“搭积木”还是“修泥潭”。

下一篇会写“发送区增强”:HEX 发送、转义解析、CRC 追加、自动发送,如何在一个统一入口里做干净。

如果对您有帮助的话,能否支持一下博主?
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇