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