自学内容网 自学内容网

QT 串口上位机读卡显示

目录

一.   QT创建工程

二.   软件更换图标 

三.   QT打包


一.   QT创建工程

文件新建,选择创建一个桌面QT。

重命名RFID,并选择工程保存路径

 RFID.pro

QT       += core gui serialport
#串行串口

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = RFID
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui
#使用C++11
CONFIG += c++11

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QByteArray>
#include <QTimer>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT  // Qt 中的宏,支持信号和槽机制

public:
    // 构造函数,初始化 MainWindow 对象
    explicit MainWindow(QWidget *parent = nullptr);

    // 析构函数,用于销毁 MainWindow 对象,防止内存泄漏
    ~MainWindow();

private slots:
    // 当发送按钮被点击时执行的槽函数,用于向串口发送数据
    void on_sendButton_clicked();  
    
    // 读取串口接收到的数据,当串口有数据可读时调用
    void readData();               
    
    // 打开或关闭串口,响应打开按钮的点击事件
    void on_openButton_clicked();  
    
    // 扫描可用的串口端口列表,并在界面中显示
    void scanAvailablePorts();     

private:
    Ui::MainWindow *ui;  // UI 界面类的指针,用于访问 UI 中的控件
    QSerialPort *serial; // 串口对象的指针,处理与串口相关的通信操作
    QTimer *scanTimer;   // 定时器指针,用于定时扫描可用的串口

    // 配置串口参数(如波特率、数据位、停止位等)
    void configureSerialPort();  

    // 更新状态栏的消息,提示用户当前串口的状态
    void updateStatusMessage();  
};

#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication>

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

    MainWindow w;
    w.show();

    return a.exec();
}

 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPortInfo>
#include <QByteArray>
#include <QDebug>
#include <QString>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    serial(new QSerialPort(this)),
    scanTimer(new QTimer(this))  // 初始化定时器
{
    ui->setupUi(this);

    // 设置窗口标题 左上角的
    setWindowTitle("白卡写卡软件");

    // 扫描可用的串口
    connect(scanTimer, &QTimer::timeout, this, &MainWindow::scanAvailablePorts);
    scanTimer->start(1000); // 每秒扫描一次

    connect(ui->sendButton, &QPushButton::clicked, this, &MainWindow::on_sendButton_clicked);
    connect(ui->openButton, &QPushButton::clicked, this, &MainWindow::on_openButton_clicked);
    connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);

    // 初次扫描端口
    scanAvailablePorts();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::scanAvailablePorts()
{
    QString currentPortName = ui->portComboBox->currentText();
    bool currentPortStillAvailable = false;

    ui->portComboBox->clear();
    const auto serialPortInfos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &serialPortInfo : serialPortInfos) {
        ui->portComboBox->addItem(serialPortInfo.portName());
        if (serialPortInfo.portName() == currentPortName) {
            currentPortStillAvailable = true;
        }
    }

    // 如果当前选择的端口仍然可用,则重新选择它
    if (currentPortStillAvailable) {
        ui->portComboBox->setCurrentText(currentPortName);
    } else if (ui->portComboBox->count() > 0) {
        ui->portComboBox->setCurrentIndex(0);
    }

    updateStatusMessage();
}

void MainWindow::configureSerialPort()
{
    if (serial->isOpen()) {
        serial->close();
    }

    QString portName = ui->portComboBox->currentText();
    serial->setPortName(portName);
    serial->setBaudRate(QSerialPort::Baud115200);  // 设置波特率为 115200
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);

    if (serial->open(QIODevice::ReadWrite)) {
        ui->statusBar->showMessage("串口打开: " + portName);
        scanTimer->stop();  // 成功打开串口后停止扫描
    } else {
        ui->statusBar->showMessage("无法打开串口: " + portName);
    }
}

void MainWindow::on_openButton_clicked()
{
    configureSerialPort();
    updateStatusMessage();
}

void MainWindow::updateStatusMessage()
{
    if (serial->isOpen()) {
        ui->statusBar->showMessage("串口打开: " + ui->portComboBox->currentText());
    } else {
        ui->statusBar->showMessage("串口未连接");
    }
}

void MainWindow::on_sendButton_clicked()
{
    if (!serial->isOpen()) {
        ui->statusBar->showMessage("串口未连接");
        return;
    }

    // 获取用户输入并转换为字节数组
    QString inputText = ui->inputLineEdit->text();
    // 将十进制字符串转换为整数
    bool ok;
    int decimalValue = inputText.toInt(&ok);

    if (!ok) {
        qDebug() << "Invalid decimal input";
        return;
    }

    // 确保整数值在 0 到 255 之间,因为我们要将其表示为一个字节
    if (decimalValue < 0 || decimalValue > 255) {
        qDebug() << "Decimal value out of range (0-255)";
        return;
    }

    // 创建并初始化 QByteArray
    QByteArray data(11, 0); // 预先分配 11 个字节并初始化为 0
    data[0] = static_cast<char>(0x40);
    data[1] = static_cast<char>(0xA9);
    data[2] = static_cast<char>(0x00);
    data[3] = static_cast<char>(0x04);
    data[4] = static_cast<char>(0x00);
    data[5] = static_cast<char>(0x00);
    data[6] = static_cast<char>(0x00);
    data[7] = static_cast<char>(0x00); // 预留一个位置
    data[8] = static_cast<char>(0x00);
    data[9] = static_cast<char>(0x00);
    data[10] = static_cast<char>(0x0D);

    // 将整数转换为十六进制字节
    char hexByte = static_cast<char>(decimalValue);

    // 将该字节放入 QByteArray 的第八个位置(索引 7)
    data[7] = hexByte;

    // 发送数据
    serial->write(data);
}

void MainWindow::readData()
{
    if (!serial->isOpen()) {
        ui->statusBar->showMessage("串口未连接");
        return;
    }

    QByteArray receivedData = serial->readAll();

    // 显示接收到的全部数据(十六进制格式)
    ui->receivedDataTextEdit->append(receivedData.toHex().toUpper());

    // 获取第13个字节的数据并显示在特定窗口
    if (receivedData.size() >= 13) {
        // 获取第13个字节的数据
        unsigned char byte13 = static_cast<unsigned char>(receivedData[12]);

        // 将字节转换为十进制表示
        int decimalValue = static_cast<int>(byte13);

        // 将十进制整数转换为字符串
        QString decimalString = QString::number(decimalValue);

        // 在特定窗口中显示十进制数据
        ui->byte13Label->setText(decimalString);
    }
}

mainwindow.ui

1.选择串口的下拉框(Combo Box) : portComboBox

2.打开按钮 : openButton

3.写卡号输入框(Line Edit) : inputLineEdit

4.写卡按钮 : sendButton

5.串口数据窗口(Text Edit) : receivedDataTextEdit

6.当前卡号显示 (Label): byte13Label

运行效果:

二.   软件更换图标 

在工程目录新建文件夹resources

 里面放ico格式的图片

iconfont-阿里巴巴矢量图标库

PNG转ICO - 在线转换图标文件

 在 Qt Creator 中,右键单击项目名称并选择"添加新文件" > "Qt" > "Qt Resource File",将资源文件添加到项目中

将资源文件命名为"resources.qrc"

在 Qt Creator 中打开"resources.qrc"文件,右键单击文件并选择"添加前缀"。添加一个名称,例如"/icons"

 

 右键单击新创建的前缀("/icons"),然后选择"添加文件",将步骤 2 中的 `.ico` 文件添加到资源文件中

更新 .pro 文件

 在 Qt Creator 中打开项目的 .pro 文件。

RC_ICONS = resources/rfid.ico

三.   QT打包

以 Release 方式编译生成 exe 程序:

生成的程序运行正常之后,找到项目的生成目录,比如 项目源码路径:C:\Users\Administrator\Desktop\WR\WR\RFID 。
它的项目生成目录是 C:\Users\Administrator\Desktop\WR\build-RFID-Desktop_Qt_5_4_0_MinGW_32bit-Release 。
进入这个文件夹,在进入它的子文件夹 release 里面,找到 RFID.exe,将这个exe 复制到一个新的单独的文件夹里用于发布,比如存到 C:\Users\Administrator\Desktop\WR\WR\Card 文件夹里面。

然后从开始菜单打开 Qt 命令行,

输入命令:cd  C:\Users\Administrator\Desktop\WR\WR\Card
然后使用 windeployqt 工具命令:windeployqt RFID.exe

 打包完成

直接可以运行

封包软件

 打开Enigma Virtual Box,浏览封包的主程序

 点击右下角的“文件选项”按钮,打开“文件选项”窗口,并勾选其中的“压缩文件”,如下图中红框所示。压缩后的单文件会小得多,所以建议勾选。

点击左下角的“增加”按钮,开始增加文件,如下图所示。

确认后

 

点击确定

执行封包

运行

这时候card路径下生成一个新的exe可以发送,也不会少包

链接: https://pan.baidu.com/s/1U9RA7MdLsOJZUqYMW3FUjg?pwd=ff5q 提取码: ff5q 


原文地址:https://blog.csdn.net/weixin_46286415/article/details/142215539

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!