Qt5实现Windows平台串口通信

简介: Qt5实现Windows平台串口通信

一、环境配置

  1. 开发环境: Qt 5.15.2+ (MSVC 2019编译器) Windows 10/11

  2. 依赖配置

    # .pro文件配置
    QT += serialport widgets
    LIBS += -lQt5SerialPort
    

二、界面设计

1. 控件布局

<!-- mainwindow.ui -->
<widget class="QMainWindow" name="MainWindow">
    <layout class="QGridLayout">
        <!-- 串口配置区 -->
        <item row="0" column="0">
            <QLabel text="串口号"/>
        </item>
        <item row="0" column="1">
            <QComboBox objectName="cmbPort"/>
        </item>

        <!-- 波特率设置 -->
        <item row="1" column="0">
            <QLabel text="波特率"/>
        </item>
        <item row="1" column="1">
            <QComboBox objectName="cmbBaudRate"/>
        </item>

        <!-- 控制按钮 -->
        <item row="2" column="0" colspan="2">
            <QPushButton text="打开串口" objectName="btnOpen"/>
        </item>

        <!-- 数据收发区 -->
        <item row="3" column="0">
            <QPlainTextEdit objectName="txtSend"/>
        </item>
        <item row="3" column="1">
            <QPlainTextEdit objectName="txtRecv"/>
        </item>

        <!-- 发送按钮 -->
        <item row="4" column="0" colspan="2">
            <QPushButton text="发送数据" objectName="btnSend"/>
        </item>
    </layout>
</widget>

三、核心代码实现

1. 头文件定义

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>

QT_BEGIN_NAMESPACE
namespace Ui {
    class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
   
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_btnOpen_clicked();
    void on_btnSend_clicked();
    void serialRead();

private:
    void initSerialPort();
    void populatePorts();

    Ui::MainWindow *ui;
    QSerialPort *serial;
};

#endif // MAINWINDOW_H

2. 实现文件

// mainwindow.cpp
#include "mainwindow.h"
#include <QSerialPortInfo>
#include <QByteArray>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
   
    ui->setupUi(this);

    // 初始化串口
    serial = new QSerialPort(this);
    initSerialPort();
    populatePorts();

    // 信号槽连接
    connect(ui->btnOpen, &QPushButton::clicked, this, &MainWindow::on_btnOpen_clicked);
    connect(ui->btnSend, &QPushButton::clicked, this, &MainWindow::on_btnSend_clicked);
    connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialRead);
}

MainWindow::~MainWindow()
{
   
    if(serial->isOpen()) serial->close();
    delete ui;
}

void MainWindow::initSerialPort()
{
   
    // 配置默认参数
    serial->setBaudRate(QSerialPort::Baud9600);
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
}

void MainWindow::populatePorts()
{
   
    ui->cmbPort->clear();
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
   
        ui->cmbPort->addItem(info.portName());
    }
}

void MainWindow::on_btnOpen_clicked()
{
   
    if(serial->isOpen()) {
   
        serial->close();
        ui->btnOpen->setText("打开串口");
    } else {
   
        serial->setPortName(ui->cmbPort->currentText());
        if(serial->open(QIODevice::ReadWrite)) {
   
            ui->btnOpen->setText("关闭串口");
        } else {
   
            QMessageBox::critical(this, "错误", serial->errorString());
        }
    }
}

void MainWindow::on_btnSend_clicked()
{
   
    QByteArray data = ui->txtSend->toPlainText().toUtf8();
    if(!data.isEmpty()) {
   
        qint64 bytes = serial->write(data);
        if(bytes == -1) {
   
            QMessageBox::warning(this, "发送失败", serial->errorString());
        }
    }
}

void MainWindow::serialRead()
{
   
    QByteArray buffer = serial->readAll();
    if(!buffer.isEmpty()) {
   
        ui->txtRecv->appendPlainText(QString::fromUtf8(buffer));
    }
}

四、功能扩展

1. 十六进制支持

// 在发送函数中添加HEX转换
void MainWindow::on_btnSend_clicked()
{
   
    QString text = ui->txtSend->toPlainText();
    QByteArray data;

    if(ui->chkHexSend->isChecked()) {
   
        bool ok;
        data = QByteArray::fromHex(text.toUtf8(), &ok);
        if(!ok) {
   
            QMessageBox::warning(this, "错误", "无效的HEX格式");
            return;
        }
    } else {
   
        data = text.toUtf8();
    }

    serial->write(data);
}

2. 数据校验

// 在配置函数中添加校验位设置
void MainWindow::setParity(QSerialPort::Parity parity) {
   
    serial->setParity(parity);
}

// 示例:CRC16校验
quint16 MainWindow::calculateCRC(const QByteArray &data) {
   
    quint16 crc = 0xFFFF;
    for(auto byte : data) {
   
        crc ^= (quint16)byte << 8;
        for(int i=0; i<8; i++) {
   
            if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
            else crc <<= 1;
        }
    }
    return crc;
}

五、调试技巧

  1. 虚拟串口测试: 使用VSPD创建虚拟串口对(如COM3 <-> COM4) 在程序中选择不同端口测试双向通信

  2. 数据监控

    // 添加调试输出
    qDebug() << "Received:" << buffer.toHex(' ') << "Length:" << buffer.size();
    
  3. 流量控制

    // 启用硬件流控制
    serial->setFlowControl(QSerialPort::HardwareControl);
    

六、编译与运行

  1. 构建配置

    qmake mainwindow.pro
    make
    
  2. 运行验证: 确保COM端口未被占用 通过设备管理器确认串口参数匹配

参考代码 Qt5串口通信程序 www.youwenfan.com/contentalf/69949.html

七、常见问题处理

现象 解决方案
无法打开串口 检查端口号是否正确,关闭占用程序
数据丢失 增加接收缓冲区,优化读取频率
显示乱码 统一使用UTF-8编码,添加校验逻辑
高波特率不稳定 降低波特率,检查线缆质量

八、工程结构

SerialDemo/
├── Src/
│   ├── main.cpp
│   ├── mainwindow.cpp
│   └── mainwindow.h
├── Res/
│   └── mainwindow.ui
└── SerialDemo.pro
相关文章
|
1月前
|
安全 Linux iOS开发
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
320 53
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
1月前
|
Linux API iOS开发
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
184 14
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
2月前
|
安全 Linux API
JEB Pro v5.31 (macOS, Linux, Windows) - 逆向工程平台
JEB Pro v5.31 (macOS, Linux, Windows) - 逆向工程平台
146 0
|
3月前
|
Unix Linux 编译器
解决在Windows平台上运行Golang程序时出现的syscall.SIGUSR1未定义错误。
通过这种结构,你的代码既可以在支持 SIGUSR1 信号的系统上正常工作,又可以在不支持这些信号的 Windows 系统上编译通过,确保跨平台的兼容性和功能的完整性。
175 0
|
Unix Linux iOS开发
Splunk Enterprise 10.0.0 (macOS, Linux, Windows) - 搜索、分析和可视化,数据全面洞察平台
Splunk Enterprise 10.0.0 (macOS, Linux, Windows) - 搜索、分析和可视化,数据全面洞察平台
109 0
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
480 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
568 0
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
755 2

推荐镜像

更多
  • qt
  • 下一篇
    oss云网关配置