【QT常用技术讲解】QSerialPort串口开发,包含文件发送功能

前言

串口通信是很古老的通信方式,适合数据传输量少的设备搭建为通信模块,本篇不延展串口历史,而是用一个应用工具关联介绍一些应用场景。

效果图

本篇的源码可以通用编译(window、Linux等),源码请查看资源。

开源的串口工具

串口应用功能不复杂,网络上可以下载到相关的工具,很方便做技术调研,下面简要介绍下window系统和Linux系统常用的串口工具。

window串口工具

1、串口助手

功能比较齐全,可以以十六进制/字符进行发送/接收,提供文件发送/接收功能等。

2、串口模拟工具vspd

如上图是在右边填写COM1和COM2,并点击【添加端口】之后,在左边就看到有两个虚拟串口了,这个工具是帮助我们在window的驱动层常见了COM1->COM2,COM2->COM1的虚拟串口,这两个串口是绑定使用的,在下面的【设备管理器】界面更容易理解:

因为大部分的笔记本都没有串口了,使用这个工具就能在自己的笔记本上完成串口应用调试。

基于这样虚拟串口工具的特性,我们还能开发一个远程串口工具,流程如下:

终端A部署了[客户端]--通过socket发送信息-->终端B部署[服务端]--接收客户端发送过来的信息,把命令信息写入到串口COM1-->COM2绑定瘦终端C(比如读卡器)

绑定瘦终端C(比如读卡器)通过COM2--返回结果-->COM1--终端B[服务端]接收信息后,通过socket返回信息-->终端A[客户端]

有远程桌面操作串口需求场景的,可以使用以上思路构建。

Linux串口工具

1、自带的cutecom

Linux串口工具cuteCOM源码(工具包含发送文件功能)这个是我分享过的工具源码

其他的需要apt下载,功能都比较简单,我这里就不列举了,如果是用测试ARM架构的Linux,可以试试Minicom。

功能讲解

1、串并口文件设置

这个菜单是用来添加自定义的串口,如果你的信创终端,要增加多个串口,这些串口不一定是COM前缀开头的文件,这个时候,市面上通用的串口工具都没法用,本篇的应用来源于实际的信创终端项目串口检测应用。

配置完成之后,在串口测试下拉框就可以选择了,这里就不展开讲解了,提供过思路给刚好有此类需求场景的人。

2、串口测试

1、获取系统串口信息

通过QSerialPortInfo 获取

复制代码
// 搜索所有可用串口
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        QSerialPort serial;
        serial.setPort(info);
        ui->comboBox->addItem(serial.portName());
        if (serial.open(QIODevice::ReadWrite)){
            qDebug() << "==>" << serial.portName();
        }
    }

2、波特率设置

手动设置上去的

3、打开串口

核心代码就是:serialPort->open(QIODevice::ReadWrite)

复制代码
void MainWindow::on_pushButton_8_clicked()
{
    if(ui->pushButton_8->text() == tr("打开"))
    {
        // 串口设置
        serialPort->setPortName(ui->comboBox->currentText());
        serialPort->setBaudRate(ui->comboBox_2->currentText().toInt());
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setStopBits(QSerialPort::OneStop);
        serialPort->setParity(QSerialPort::NoParity);

        // 打开串口
        if (serialPort->open(QIODevice::ReadWrite))
        {
            qDebug() << "串口打开成功";
            m_recvData.clear();
            connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::readSerialData);
        }
        else
        {
            qDebug() << "串口打开失败";
            QMessageBox::warning(this, "错误", "无法打开串口: " + serialPort->portName());
            return;
        }
        ui->pushButton_8->setText("关闭");
        ui->comboBox->setEnabled(false);
        ui->comboBox_2->setEnabled(false);
    }
    else
    {
        serialPort->close();
        qDebug() << "串口关闭成功";
        ui->pushButton_8->setText("打开");
        ui->comboBox->setEnabled(true);
        ui->comboBox_2->setEnabled(true);
    }
}

4、串口发送功能

核心代码是:serialPort->write(data);

复制代码
// 发送数据函数
void MainWindow::sendData(const QByteArray &data)
{
    if (!serialPort->isOpen()) {
        QMessageBox::warning(this, "警告", "请先打开串口!");
        return;
    }

    qint64 bytesWritten = serialPort->write(data);
    if (bytesWritten == -1) {
        QMessageBox::warning(this, "错误", "发送数据失败");
    }
    else if (bytesWritten != data.size()) {
        QMessageBox::warning(this, "警告", "数据未完全发送");
    }
}

5、 十六进制模式方式发送

发送之前,对内容转换为十六进制

复制代码
        QByteArray data = hexStringToBytes(sendText);
        if (!data.isEmpty()) {
            qDebug() << "发送十六进制数据:" << bytesToHexString(data);
            sendData(data);
        }

// 十六进制字符串转字节数组
QByteArray MainWindow::hexStringToBytes(const QString &hexStr)
{
    QByteArray byteArray;
    QString trimmed = hexStr.trimmed();
    QStringList hexValues = trimmed.split(' ');

    for (const QString &hexValue : hexValues) {
        if (hexValue.isEmpty()) continue;

        bool ok;
        char byte = static_cast<char>(hexValue.toInt(&ok, 16));
        if (ok) {
            byteArray.append(byte);
        }
        else {
            QMessageBox::warning(this, "错误", "无效的十六进制值: " + hexValue);
            return QByteArray();
        }
    }

    return byteArray;
}

6、字符方式发送

发送之前,对内容转换为utf-8格式

复制代码
        // 字符模式
        QByteArray data = sendText.toUtf8();
        qDebug() << "发送字符数据:" << sendText;
        sendData(data);

7、文件发送

以块方式循环读取文件内容,然后发送到对端

复制代码
void MainWindow::on_pushButton_sendFile_clicked()
{
    if (!serialPort->isOpen()) {
        QMessageBox::warning(this, "警告", "请先打开串口!");
        return;
    }

    // 直接弹出文件选择对话框
    QString fileName = QFileDialog::getOpenFileName(this, "选择要发送的文件", "", "所有文件 (*)");
    if (fileName.isEmpty()) {
        return;
    }

    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, "错误", "无法打开文件: " + fileName);
        return;
    }

    QFileInfo fileInfo(fileName);
    qDebug() << "准备发送文件:" << fileName << "大小:" << fileInfo.size() << "字节";

    // 创建进度对话框
    QProgressDialog progress("发送文件中...", "取消", 0, file.size(), this);
    progress.setWindowTitle("发送文件");
    progress.setWindowModality(Qt::WindowModal);
    progress.show();

    // 分块读取和发送文件
    const int chunkSize = 1024;
    qint64 totalSent = 0;
    QByteArray data;

    while (!file.atEnd()) {
        if (progress.wasCanceled()) {
            break;
        }

        data = file.read(chunkSize);

        qint64 bytesWritten = serialPort->write(data);
        if (bytesWritten == -1) {
            QMessageBox::warning(this, "错误", "发送文件失败");
            break;
        }

        if (!serialPort->waitForBytesWritten(5000)) {
            QMessageBox::warning(this, "错误", "写入超时");
            break;
        }

        totalSent += bytesWritten;
        progress.setValue(totalSent);
        QApplication::processEvents();

        // 添加小延迟,避免过快发送导致接收方处理不过来
        QThread::msleep(10);
    }

    file.close();

    if (totalSent == fileInfo.size()) {
        QMessageBox::information(this, "完成", "文件发送完成!\n发送字节数: " + QString::number(totalSent));
    } else {
        QMessageBox::information(this, "中断", "文件发送已中断\n已发送字节数: " + QString::number(totalSent));
    }
}

使用本应用的文件发送功能,发送给串口助手,经过测试,支持文本文件、图片文件传输。可能你会绝得串口工具没必要传输这么多字符的内容,常用场景确实是这样。但是,在不方便使用USB、网络挂载的情况下,串口通常是可以作为临时传输通道的,这个不好明说。

相关推荐
YxVoyager17 小时前
Qt C++ :QLayout 布局管理
c++·qt
共享家95271 天前
QT-常用控件(一)
开发语言·qt
ajassi20001 天前
开源 C++ QT QML 开发(十二)通讯--TCP客户端
c++·qt·开源
nnnnichijou1 天前
Qt Quick 3D-机械臂模型显示与交互
qt·3d·交互
长源Gingko1 天前
Windows中在QTCreator中调试,提示缺少debug information files问题的解决
windows·qt
SundayBear1 天前
Qt 开发修炼指南:从入门到通透的实战心法
开发语言·qt·嵌入式
ajassi20001 天前
开源 C++ QT QML 开发(十)通讯--串口
c++·qt·开源
BingeBlog1 天前
[01] Qt的UI框架选择和对比
开发语言·c++·笔记·qt·ui·开源软件
扶尔魔ocy1 天前
【QT常用技术讲解】opencv实现摄像头图像检测并裁剪物体
开发语言·qt·opencv