1. 课程导入

工业设备应用开发与普通桌面软件最大的区别在于:软件必须与真实设备、传感器、执行机构、PLC、运动控制卡、串口屏等硬件长期稳定协同工作。Qt 作为跨平台 C++ 应用框架,凭借其成熟的信号与槽机制、丰富的 UI 组件、强大的网络与串口模块,以及良好的实时界面刷新能力,成为工业上位机、HMI、设备调试工具和产线监控系统的主流选择。本课程的目标,是带领大家从零搭建 Qt 工业设备应用的知识体系,并最终具备独立开发一套可运行、可调试、可交付的工业设备软件的能力。

一、学习目标:从会写界面到能控设备

学习本课程后,你应当能够完成以下四类任务:

  • 界面层:使用 Qt Widgets 或 Qt Quick 构建工业 HMI,包括参数配置页、实时曲线、报警列表、设备状态灯与手动控制面板。
  • 通信层:通过 QSerialPort、QTcpSocket、QUdpSocket、Modbus 等完成与 PLC、仪表、运动控制器的数据交互。
  • 业务层:把设备状态机、工艺流程、配方管理、数据记录与报警逻辑组织成可维护的模块。
  • 工程层:掌握 qmake/CMake 构建、调试、日志、打包部署与现场排障方法。
核心判断标准:一个合格的 Qt 工业应用,不是“界面好看”,而是“设备连得上、数据读得准、指令下得去、异常停得住、日志查得到”。

二、核心概念:工业 Qt 应用的五个关键词

在进入具体编码之前,先建立五个贯穿全课程的核心概念。

概念 含义 在工业场景中的体现
信号与槽 Qt 的对象间通信机制,解耦事件产生与处理 串口收到数据后触发 readyRead,界面自动刷新
事件循环 QApplication 驱动的主循环,负责分发事件与定时器 界面不卡死、定时轮询设备状态
线程与并发 QThread、QtConcurrent、moveToThread 通信与解析放在工作线程,UI 线程只负责显示
协议解析 把字节流转换为有意义的工程值 Modbus 寄存器、自定义帧头帧尾、CRC 校验
状态机 用有限状态描述设备运行逻辑 空闲、就绪、运行、报警、急停之间的切换

其中,信号与槽和事件循环是 Qt 的“骨架”,线程与协议解析是工业软件的“肌肉”,状态机则是“大脑”。四者配合,才能让软件在设备现场稳定运行。

三、整体框架:一套工业 Qt 应用的典型分层

工业设备软件通常采用分层架构,避免把串口读写、协议解析和界面刷新全部塞进一个类里。推荐的分层如下:

  • 表现层:主窗口、参数页、曲线控件、报警表格,只负责展示与用户输入。
  • 业务层:设备管理、配方管理、报警管理、数据记录,负责流程与规则。
  • 通信层:串口、TCP、Modbus、自定义协议,负责收发与连接管理。
  • 设备层:PLC、传感器、伺服、扫码枪、相机等真实硬件。

下面的 SVG 展示了这一分层结构以及数据在层间的流动方向:

Qt 工业设备应用分层架构与数据流 表现层(UI 线程) 主窗口 · 参数配置 · 实时曲线 · 报警列表 · 手动控制面板 业务层 设备管理 · 状态机 · 配方管理 · 报警管理 · 数据记录 通信层(工作线程) QSerialPort · QTcpSocket · Modbus · 自定义协议解析 · 连接管理 设备层 PLC · 传感器 · 伺服驱动器 · 扫码枪 · 工业相机 · 仪表 用户操作 / 界面请求 业务指令 / 状态更新 协议帧 / 读写请求 设备数据 / 应答帧 解析结果 / 报警事件 界面刷新 / 曲线更新 数据自下而上采集,指令自上而下下发;UI 线程与通信线程通过信号与槽解耦

四、开发环境搭建:从安装到第一个可运行工程

工业项目推荐使用 Qt 5.15 LTS 或 Qt 6.x LTS,配合 CMake 构建。以下以 Windows + Qt 6 + CMake 为例说明关键步骤。

  1. 安装 Qt Online Installer,勾选 Qt 6.x 下的 MSVC 2019 64-bit 或 MinGW 64-bit,并勾选 Qt Serial Port、Qt Network 模块。
  2. 安装对应编译器与 CMake,确保 cmake --version 与 qmake -v 均可执行。
  3. 创建工程目录,编写 CMakeLists.txt,链接串口与网络模块。
  4. 编写最小可运行程序,验证 Qt 环境与串口模块可用。
cmake_minimum_required(VERSION 3.16)
project(IndustrialDemo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets SerialPort Network)

add_executable(IndustrialDemo
    main.cpp
    mainwindow.cpp
    mainwindow.h
)

target_link_libraries(IndustrialDemo PRIVATE
    Qt6::Widgets
    Qt6::SerialPort
    Qt6::Network
)

一个最小的串口扫描程序可以这样写,用于确认环境是否正常:

#include <QApplication>
#include <QSerialPortInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    const auto ports = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : ports) {
        qDebug() << "端口:" << info.portName()
                 << "描述:" << info.description();
    }
    return 0;
}
建议在工程初期就统一使用 CMake,而不是 qmake。工业项目往往需要集成第三方库、交叉编译到 ARM 工控机,CMake 的可移植性更好。

五、常见误区与复盘

初学者在工业 Qt 开发中最容易踩的坑,往往不是语法问题,而是工程习惯问题。

  • 误区一:所有逻辑都写在 UI 类里。结果主窗口越来越臃肿,串口、协议、业务全部耦合,后期无法维护。应尽早拆分通信类与业务类。
  • 误区二:在 UI 线程里做阻塞读写。串口等待、网络超时会让界面卡死。通信必须放入工作线程或使用异步接口。
  • 误区三:忽略异常与断线重连。现场设备会掉线、会重启,软件必须能检测连接状态并自动恢复。
  • 误区四:没有日志。设备现场出问题时,没有日志几乎无法定位。建议从第一天就接入分类日志。
工业软件的第一原则是“可观测、可恢复、可追溯”。界面只是表象,通信稳定性、状态机正确性和日志完整性才是现场交付的底线。