QT 串口上位机读卡显示

news2024/11/15 18:00:31

目录

一.   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 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2134136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SX_VMware联网_23

利用Nat模式联网&#xff0c;NAT模式&#xff08;Network Address Translation&#xff09;&#xff1a; 在NAT模式下&#xff0c;虚拟机通过主机的网络接口访问外部网络。 虚拟机之间可以相互通信&#xff0c;也可以访问主机网络以及互联网。 虚拟机使用私有IP地址&#xff0c…

健身管理|基于java的健身管理系统小程序(源码+数据库+文档)

健身管理系统|健身管理系统小程序 目录 基于java的健身管理系统小程序 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&…

磁盘内存大小文件树WizTree(找内存分布)

背景 我想要清理C盘&#xff0c;但是不知道那些地方占据内存最多 https://www.diskanalyzer.com/downloadWizTree is the fastest disk space analyzer for Windows. Download the latest version here. Use it to quickly locate and remove space hogs from your hard driv…

k8s(kubernetes)的PV / PVC / StorageClass(理论+实践)

NFS总是不支持PVC扩容 先来个一句话总结&#xff1a;PV、PVC是K8S用来做存储管理的资源对象&#xff0c;它们让存储资源的使用变得可控&#xff0c;从而保障系统的稳定性、可靠性。StorageClass则是为了减少人工的工作量而去自动化创建PV的组件。所有Pod使用存储只有一个原则&…

数据库的索引是什么?

索引就是类似书本的目录一样&#xff0c;拿字典来说&#xff0c;索引存储的记录地址相当于字典的页数&#xff0c;索引存储的键值相等于字典的某个字。我们可以在目录里面快速地浏览&#xff0c;找到某个关键字&#xff0c;我们在翻到具体的页数看字的解释。举例&#xff1a;我…

机器学习特征构建与特征筛选

前言 上一篇文章讲述了原始特征分析和处理&#xff0c;保障后续拿到的是干净的特征变量&#xff0c;但实际这些特征对于建模不一定是有效的&#xff0c;所以需要在原始特征的基础上&#xff0c;结合业务场景做特征变量的衍生&#xff0c;提升数据的表达能力。此外&#xff0c;…

下载 llama2-7b-hf 全流程【小白踩坑记录】

1、文件转换 在官网 https://ai.meta.com/llama/ 申请一个账号&#xff0c;选择要下载的模型&#xff0c;会收到一个邮件&#xff0c;邮件中介绍了下载方法 执行命令 git clone https://github.com/meta-llama/llama.git​ &#xff0c;然后执行 llama/download.sh&#xff0c…

实习项目|苍穹外卖|day9

实战作业。 用户端新增功能 1. 查询历史订单 接口设计 返回的是orderorderdetails&#xff08;那我这里就先查order&#xff0c;再根据order_id查&#xff09; 分页 pageHelper的使用&#xff1a; //controller相关函数GetMapping("/historyOrders")ApiOperati…

线性回归_梯度下降法

from numpy import * import matplotlib.pyplot as plt1.导入数据 # 1.导入数据 # 模型 y wx b points genfromtxt(linear_regress_lsm_data.csv, delimiter,) length len(points) print(point count %d%length) x array(points[:, 0]) y array(points[:, 1]) plt.scatt…

浅谈工业配电系统中漏电产生的成因以及应对方案

摘要 在现代工业厂房的配电系统中&#xff0c;绝缘检测仪作为保障电气设备安全运行的重要工具&#xff0c;发挥着关键作用。本文探讨了绝缘检测仪在工业厂房配电系统中的应用背景、工作原理、具体应用以及其对设备维护与安全管理的影响。通过分析绝缘检测仪在实际操作中的优势…

数据结构修炼——顺序表和链表的区别与联系?从入门到进阶!

目录 一、线性表二、顺序表2.1 概念及结构2.2 接口实现2.3 一些思考以及顺序表的缺点 三、链表3.1 概念及结构3.2 链表的分类3.3 链表的实现3.3.1 无头单向非循环链表3.3.2 带头双向循环链表 四、顺序表和链表的区别 一、线性表 线性表&#xff08;linear list&#xff09;是n…

初级练习[3]:Hive SQL子查询应用

目录 环境准备看如下链接 子查询 查询所有课程成绩均小于60分的学生的学号、姓名 查询没有学全所有课的学生的学号、姓名 解释: 没有学全所有课,也就是该学生选修的课程数 < 总的课程数。 查询出只选修了三门课程的全部学生的学号和姓名 环境准备看如下链接 环境准备h…

【蓝桥杯省赛真题53】Scratch游乐场 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解

目录 scratch游乐场 一、题目要求 编程实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、python资料 scratch游…

Upstage 将发布新一代 LLM “Solar Pro “预览版

Solar Pro 是最智能的 LLM&#xff0c;经过优化可在单 GPU 上运行&#xff0c;性能超过微软、Meta 和谷歌等科技巨头的模型。 加州圣何塞2024年9月11日电 /美通社/ – Upstage 今天宣布发布其下一代大型语言模型 (LLM) Solar Pro 的预览版。加州圣何塞2024年9月11日电 /美通社…

ElementUI大坑Notification修改样式

默认<style lang"scss" scoped>局部样式&#xff0c;尝试用deep透传也无效 实践成功方法&#xff1a;单独写一个style <style> .el-notification{position: absolute !important;top: 40% !important;left: 40% !important; } </style> 也支持自…

无头服务(Headless Service)

无头服务 ​ 无头服务&#xff08;Headless Service&#xff09;是 Kubernetes 中的一种特殊服务类型&#xff0c;主要用于提供稳定的网络标识&#xff0c;而不需要通过负载均衡来分配流量。它允许直接访问 Pod&#xff0c;而不经过集群内的负载均衡器&#xff0c;并且通常用于…

C# net跨平台上位机开发(avalonia)附demo源码

介绍: 目前微软还没有跨平台桌面程序的开发框架。github上有一个团队开始自行研发跨平台桌面框架,其中一款叫avalonia。avalonia 采用 Xaml+C#,类似于wpf,可运行于.netframework,.netcore,是相对比较成熟的.net跨平台桌面应用技术。下面介绍如何创建 avalonia项目;如何在…

mysql_getshell的几种方法

mysql_getshell 一、mysql的--os-shell 利用原理 --os-shell就是使用udf提权获取WebShell。也是通过into oufile向服务器写入两个文件&#xff0c;一个可以直接执行系统命令&#xff0c;一个进行上传文件。此为sqlmap的一个命令&#xff0c;利用这条命令的先决条件&#xff1a;…

PMP--一模--解题--41-50

文章目录 14.敏捷--方法--回顾--回顾是最重要的一个实践&#xff0c;原因是它能让团队学习、改进和调整其过程。41、 [单选] 新项目中的所有团队成员都希望通过尽快交付价值来获得客户的信任。项目经理了解到一个资源已经在其他项目中与发起人一起工作。某资源似乎在使用个人影…

ICM20948 DMP代码详解(20)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;19&#xff09; 本回继续对inv_icm20948_read_mems_reg函数的其余内容进行解析。为了便于理解和回顾&#xff0c;再次贴出inv_icm20948_read_mems_reg函数源码&#xff0c;在EMD-Core\sources\Invn\Devices\Drivers\I…