本示例使用的发卡器:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.52de2c1bVIuGpf&ft=t&id=18645495882 

一、确定已安装Qt Serial Port组件

二、在.pro项目文件声明引用Serialport组件

三、在.h头文件内引用Serialport组件

四、在.cpp程序中实列化serial,并绑定串口接收数据的槽函数

五、打开串口并设置波特率、数据位、校验位、停止位 

void MainWindow::on_Butt_Open_clicked()
{if(ui->Butt_Open->text() == "打开串口"){//设置串口为下拉栏所选串口名serial->setPortName(ui->Com_Serial->currentText());//设置波特率switch (ui->Com_Baud->currentIndex()){case 0: serial->setBaudRate(QSerialPort::Baud4800); break;//4800case 1: serial->setBaudRate(QSerialPort::Baud9600);   break;case 2: serial->setBaudRate(QSerialPort::Baud19200); break;case 3: serial->setBaudRate(QSerialPort::Baud38400);   break;case 4: serial->setBaudRate(QSerialPort::Baud57600);   break;case 5: serial->setBaudRate(QSerialPort::Baud115200);   break;default: break;}//设置数据位数switch (ui->Com_Size->currentIndex()){case 0:serial->setDataBits(QSerialPort::Data5); break;//1位case 1:serial->setDataBits(QSerialPort::Data6); break;case 2:serial->setDataBits(QSerialPort::Data7); break;//1位case 3:serial->setDataBits(QSerialPort::Data8); break;default: break;}//设置校验位switch (ui->Com_Parity->currentIndex()){case 0:serial->setParity(QSerialPort::NoParity);   break;//无校验位case 1:serial->setParity(QSerialPort::OddParity);  break;case 2:serial->setParity(QSerialPort::EvenParity);  break;case 3:serial->setParity(QSerialPort::MarkParity);  break;default: break;}//设置停止位switch (ui->Com_Stop->currentIndex()){case 0:serial->setStopBits(QSerialPort::OneStop); break;//1位case 1:serial->setStopBits(QSerialPort::OneAndHalfStop); break;case 2:serial->setStopBits(QSerialPort::TwoStop); break;default: break;}//设置流控制//serial->setFlowControl(QSerialPort::NoFlowControl);//无流控制serial->setFlowControl(QSerialPort::SoftwareControl);//打开串口 同时判断是否成功bool info = serial->open(QIODevice::ReadWrite);if(info == true){qDebug()<<"success";//改变label颜色(指示灯)ui->label_16->setStyleSheet("background-color:rgb(0,255,0);border-radius:10px;");//关闭下拉栏设置使能ui->Com_Serial->setEnabled(false);ui->Com_Baud->setEnabled(false);ui->Com_Size->setEnabled(false);ui->Com_Parity->setEnabled(false);ui->Com_Stop->setEnabled(false);//改变按钮文本为“关闭串口”ui->Butt_Open->setText(tr("关闭串口"));ui->Label_status->setText("");}else{qDebug()<<"fail";QMessageBox::critical (this, "警告", "串口打开失败!", QMessageBox::Ok);}}else{   //关闭串口serial->clear();serial->close();//改变label颜色(指示灯)ui->label_16->setStyleSheet("background-color:rgb(255,0,0);border-radius:10px;");//恢复下拉栏设置使能ui->Com_Serial->setEnabled(true);ui->Com_Baud->setEnabled(true);ui->Com_Size->setEnabled(true);ui->Com_Parity->setEnabled(true);ui->Com_Stop->setEnabled(true);//改变按钮文本为“打开串口”ui->Butt_Open->setText(tr("打开串口"));ui->Label_status->setText("请先选择并打开与发卡器相连的串口!");}
}

 六、向串口发送读M1卡扇区数据的指令

void MainWindow::on_Butt_ReadCard_clicked()
{unsigned char authkeybuf[6];QString authkeystr=ui->Text_key->toPlainText().trimmed();int checkbuflen=checkhexdata(authkeystr,authkeybuf);if (checkbuflen!=6){QMessageBox::critical(NULL, "提示", QString::asprintf("十六进制认证密钥输入错误,请输入 %d", 6)+  " 字节的16进制认证密钥!");ui->Text_key->setFocus();return;}if (serial->isOpen()) {     //检查串口是否打开unsigned char databuff[16];databuff[0]=0x0e;databuff[1]=0x78;databuff[2]=0x17;databuff[3]=0x00;  //表示读取任意卡databuff[4]=0x00;databuff[5]=0x00;databuff[6]=0x00;databuff[7]=ui->Com_Area->currentIndex();  //扇区号databuff[8]=ui->Com_Auth->currentIndex();  //认证方式for(int i=0;i<6;i++){databuff[9+i]=authkeybuf[i];}  //认证密钥char crc= 0;for (int i=1;i<=14;i++){crc=crc xor databuff[i];}databuff[15]=crc;sendData.clear();sendData.append(reinterpret_cast<const char*>(databuff), sizeof(databuff));FuncCode=2;getdatapoint=0;serial->write(sendData);QString  dispinf=ByteArrayToHexString(sendData);ui->Text_HexData->setPlainText(dispinf);listadditems(getsystime()+"    Send:"+dispinf);}else{QMessageBox::critical (this, "警告", "请先打开与发卡器相连的串口!", QMessageBox::Ok);}
}

七、串口接收数据的槽函数返回读卡操作结果

void MainWindow::ReadData()//读取接收到的信息
{    QByteArray buf = serial->readAll();int buflen=buf.length();unsigned char databuff[buflen];std::copy(buf.begin(), buf.end(), databuff);QString str="";int crc=0;if (FuncCode>=0){                        //读、写M1、Ntag卡指令,为防止数据分包上传,先将数据存入缓冲for (int i=0;i<buflen;i++){getdatabuff[getdatapoint]=databuff[i];getdatapoint++;}for (int i=0;i<getdatapoint;i++){    //校验缓冲区内数据crc,如果校验成功即认为数据全部接收完,开始分析接收数据str =str+QString::asprintf("%02X ", getdatabuff[i]);if (i>0){crc=crc xor getdatabuff[i];}}}else{  //其他串口调试指令,显示串口接收数据for (int i=0;i<buflen;i++){          //str =str+QString::asprintf("%02X ", databuff[i]);if (i>0){crc=crc xor databuff[i];}}if(crc!=0){listadditems(getsystime()+" Receive:"+str);}}if(crc==0){  //接收数据校验成功,数据有效getdatapoint=0;listadditems(getsystime()+" Receive:"+str);QString cardhao="";QString carddata="";switch(FuncCode){case 1:  //只读卡号case 2:case 3:case 4:if(getdatabuff[0]==1){ //只返回一个字节的有效数据switch(getdatabuff[1]){case 1:str="密码认证成功,卡片序列号已知,但读取扇区内容失败!";break;case 2:str="第0块读出,但第1、2块没读出,仅扇区内容前16个字节的数据有效!";break;case 3:str="第0、1块读出,但第2块没读出,仅扇区内容前32个字节的数据有效!";break;case 8:str="未寻到卡!";break;case 9:str="两张以上卡片同时在感应区,发生冲突!";break;case 10:str="无法选择激活卡片!";break;case 11:str="密码装载失败,卡片序列号已知!";break;case 12:str="密码认证失败,卡片序列号已知!";break;}ui->Label_status->setText(str);}else{if(getdatabuff[0]==5){ //返回五个字节的有效数据str="读取卡号成功";cardhao=QString::asprintf("%02X%02X%02X%02X", getdatabuff[2], getdatabuff[3], getdatabuff[4], getdatabuff[5]);switch(getdatabuff[1]){case 0:if(FuncCode==3){str="写扇区数据成功";}else{if(FuncCode==4){str="修改扇区密钥成功";}}break;case 1:str="密码认证成功,卡片序列号已知,但读取扇区内容失败";break;case 2:str="第0块读出,但第1、2块没读出,仅扇区内容前16个字节的数据有效";break;case 3:str="第0、1块读出,但第2块没读出,仅扇区内容前32个字节的数据有效";break;case 8:str="未寻到卡!";break;case 9:str="两张以上卡片同时在感应区,发生冲突";break;case 10:str="无法选择激活卡片";break;case 11:str="密码装载失败,卡片序列号已知";break;case 12:str="密码认证失败,卡片序列号已知";break;}ui->Label_status->setText(str+",16进制卡号:"+cardhao);}else{if(getdatabuff[0]==53){ //返回五十三个字节的有效数据cardhao=QString::asprintf("%02X%02X%02X%02X", getdatabuff[2], getdatabuff[3], getdatabuff[4], getdatabuff[5]);for (int i=6;i<=getdatabuff[0];i++){carddata=carddata+QString::asprintf("%02X", getdatabuff[i])+" ";}ui->Text_Data->setPlainText(carddata);ui->Label_status->setText("读扇区数据成功,16进制卡号:"+cardhao);}}}break;case 5:break;case 6:if (getdatabuff[0]>7){cardhao="16进制卡号:"+QString::asprintf("%02X%02X%02X%02X%02X%02X%02X", getdatabuff[2], getdatabuff[3], getdatabuff[4], getdatabuff[5], getdatabuff[6], getdatabuff[7], getdatabuff[8]);}if(getdatabuff[1]==0){ui->Label_status->setText("写Ntag卡块数据成功,"+cardhao);}else{if(getdatabuff[1]==8){ui->Label_status->setText("未寻到卡!"); }else{if(getdatabuff[1]==9){ui->Label_status->setText("两张以上卡片同时在感应区,发生冲突!"); }else{if(getdatabuff[1]==12){ui->Label_status->setText("密码认证失败!"+cardhao); }else{if(getdatabuff[1]==13){ui->Label_status->setText("读卡失败,可能要带密码操作!"+cardhao); }else{ui->Label_status->setText("写Ntag卡失败,"+QString::asprintf("返回错误代码:%d",getdatabuff[1]));}}}}}break;case 7:     //读Ntag卡返回状态if (getdatabuff[0]>7){cardhao="16进制卡号:"+QString::asprintf("%02X%02X%02X%02X%02X%02X%02X", getdatabuff[2], getdatabuff[3], getdatabuff[4], getdatabuff[5], getdatabuff[6], getdatabuff[7], getdatabuff[8]);}if(getdatabuff[1]==0){for (int i=11;i<=getdatabuff[0];i++){carddata=carddata+QString::asprintf("%02X", getdatabuff[i])+" ";}ui->Text_TagData->setPlainText(carddata);ui->Label_status->setText("读Ntag卡块数据成功,"+cardhao);}else{if(getdatabuff[1]==8){ui->Label_status->setText("未寻到卡!"); }else{if(getdatabuff[1]==9){ui->Label_status->setText("两张以上卡片同时在感应区,发生冲突!"); }else{if(getdatabuff[1]==12){ui->Label_status->setText("密码认证失败!"+cardhao); }else{if(getdatabuff[1]==13){ui->Label_status->setText("读卡失败,可能要带密码操作!"+cardhao); }else{ui->Label_status->setText("读Ntag卡失败,"+QString::asprintf("返回错误代码:%d",getdatabuff[1]));}}}}}break;case 8:     //读Ntag卡号返回状态if(getdatabuff[0]==8 && getdatabuff[1]==0){cardhao=QString::asprintf("%02X%02X%02X%02X%02X%02X%02X", getdatabuff[2], getdatabuff[3], getdatabuff[4], getdatabuff[5], getdatabuff[6], getdatabuff[7], getdatabuff[8]);ui->Label_status->setText("读Ntag卡号成功,16进制卡号:"+cardhao);}else{if(getdatabuff[0]==1 && getdatabuff[1]==8){ui->Label_status->setText("未寻到卡!");}else{if(getdatabuff[0]==1 && getdatabuff[1]==9){ui->Label_status->setText("读Ntag卡号失败,感应区内的卡不是Ntag卡!");}}}break;case 9:     //校验Ntag卡密钥if(getdatabuff[0]==3 && getdatabuff[1]==0){QString packhex=QString::asprintf("%02X%02X", getdatabuff[2], getdatabuff[3]);ui->Label_status->setText("Ntag卡密钥校验成功,PACK密钥确认码:"+packhex);}else{if(getdatabuff[0]==1 && getdatabuff[1]==12){ui->Label_status->setText("Ntag卡密钥校验失败,请先读取卡号、输入8位正确的认证密钥再校验试试!");}}break;case 10:break;}}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go 语言开发中用户密码加密存储的最佳实践

在现代 Web 应用开发中&#xff0c;用户密码的安全存储是系统安全的重要环节。本文将结合 Go 语言和 GORM 框架&#xff0c;详细介绍用户密码加密存储的完整解决方案&#xff0c;包括数据库模型设计、加密算法选择、盐值加密实现等关键技术点。 一、数据库模型设计与 GORM 实践…

优化Facebook广告投放的五大关键策略

一、精确筛选目标国家用户在Audience的locations设置目标国家时&#xff0c;务必勾选"People living in this location"选项。系统默认会选择"People living in this location or recently in this location"&#xff0c;这会扩大受众范围&#xff0c;包含…

Debian-10-standard用`networking`服务的`/etc/network/interfaces`配置文件设置多网卡多IPv6

Debian-10-buster-standard用networking服务的/etc/network/interfaces配置文件设置多网卡多IPv6 Debian-10-buster-standard用networking服务的/etc/network/interfaces配置文件设置多网卡多IPv6 250703_123456 三块网卡 : enp0s3 , enp0s8 , enp0s9 /etc/network/interfac…

对话式 AI workshop:Voice Agent 全球五城开发实录

过去几个月&#xff0c;TEN Framework 团队与 Agora 和声网围绕 “对话式AI”题&#xff0c;踏上了横跨全球五大城市的精彩旅程——东京、旧金山、巴黎、北京、京都。 五场精心筹备的Workshop 场场爆满&#xff0c; 汇聚了来自当地及全球的开发者、创业者、产品经理与语音技术爱…

算法学习笔记:6.深度优先搜索算法——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学领域&#xff0c;搜索算法是解决问题的重要工具&#xff0c;其中深度优先搜索&#xff08;Depth-First Search&#xff0c;简称 DFS&#xff09;凭借其简洁高效的特性&#xff0c;在图论、回溯、拓扑排序等众多场景中发挥着关键作用。无论是 LeetCode 算法题&#…

vue create 和npm init 创建项目对比

以下是关于 vue create 和 npm init 的对比分析&#xff1a; 1. 定位与功能 vue create 定位&#xff1a;Vue 官方提供的脚手架工具&#xff0c;基于 Vue CLI&#xff0c;用于快速创建标准化的 Vue 项目&#xff0c;支持 Vue 2 和 Vue 3。功能&#xff1a;提供交互式配置&…

C++ bitset 模板类

bitset<256> 数据类型详解 bitset<256> 是 C 标准库中的一个模板类&#xff0c;用于处理固定大小的位集合&#xff08;Bit Set&#xff09;。它可以高效地操作和存储二进制位&#xff0c;特别适合需要处理大量布尔标志或简单计数的场景。 基本定义与特性 1. 模板参…

通信握手言和:PROFINET转EtherCAT网关让汽轮机振动数据“破壁”传输

某大型电厂的关键汽轮机设备采用EtherCAT振动传感器进行实时监测&#xff0c;但由于工厂PLC振动分析系统基于PROFINET协议&#xff0c;数据无法直接接入&#xff0c;导致振动数据延迟、预警滞后&#xff0c;严重影响设备健康管理。传统的人工巡检和定期维护难以捕捉早期机械故障…

golang 中当 JSON 数据缺少结构体(struct)中定义的某些字段,会有异常吗

目录关键影响示例演示潜在问题与解决方案问题 1&#xff1a;逻辑错误&#xff08;零值干扰&#xff09;问题 2&#xff1a;忽略可选字段问题 3&#xff1a;第三方库验证最佳实践总结在 Go 语言中&#xff0c;当 JSON 数据缺少结构体&#xff08;struct&#xff09;中定义的某些…

Fiddler 中文版怎么配合 Postman 与 Wireshark 做多环境接口调试?

现代项目中&#xff0c;开发、测试、预发布、生产环境往往分离配置&#xff0c;前端在开发过程中需要频繁切换接口域名、验证多环境表现。而接口升级或项目迭代时&#xff0c;还需要做回归测试&#xff0c;确保老版本接口仍能兼容&#xff0c;避免线上事故。这些环节若仅靠代码…

钉钉小程序开发技巧:getSystemInfo 系统信息获取全解析

在钉钉小程序开发中&#xff0c;获取设备系统信息是实现跨平台适配和优化用户体验的关键环节。本文将深入解析 dd.getSystemInfo 接口的使用方法、技术细节与实际应用场景&#xff0c;帮助开发者高效应对多终端开发挑战。一、接口功能与核心价值dd.getSystemInfo 是钉钉小程序提…

Java项目Maven配置JDK1.8全攻略

目录 &#x1f9e9; 一、全局环境变量配置&#xff08;推荐系统级统一&#xff09; ⚙️ 二、Maven全局配置&#xff08;多项目统一&#xff09; &#x1f4c2; 三、项目级配置&#xff08;推荐团队协作&#xff09; &#x1f4bb; 四、IDE配置&#xff08;辅助验证&#x…

使用tensorflow的线性回归的例子(六)

波士顿房价 import matplotlib.pyplot as plt %matplotlib inline import tensorflow as tf import numpy as np from sklearn.datasets import load_boston import sklearn.linear_model as sk boston load_boston() features np.array(boston.data) labels np.arra…

YOLOv11深度解析:Ultralytics新一代目标检测架构创新与实战指南

🔍 2024年Ultralytics重磅推出YOLOv11**:在精度与速度的平衡木上再进一步,参数减少22%,推理速度提升2%,多任务支持全面升级! 🚀 一、YOLOv11核心创新:轻量化与注意力机制的完美融合 YOLOv11并非颠覆性重构,而是通过模块级优化实现“少参数、高精度、快推理”的目标…

基于 SpringBoot+Vue.js+ElementUI 的 “花开富贵“ 花园管理系统设计与实现7000字论文

摘要 本论文详细阐述了基于 SpringBoot、Vue.js 和 ElementUI 的 "花开富贵" 花园管理系统的设计与实现过程。该系统旨在为花园管理者提供高效、便捷的花园信息管理平台&#xff0c;实现花卉信息、员工、客户、订单等全方位管理功能。论文首先分析了花园管理系统的研…

RESTful API 安装使用教程

一、RESTful API 简介 REST&#xff08;Representational State Transfer&#xff09;是一种基于 Web 的架构风格&#xff0c;RESTful API 是使用 HTTP 协议并遵循 REST 原则设计的 API 接口。其核心思想是&#xff1a;使用标准 HTTP 方法&#xff08;GET、POST、PUT、DELETE&…

【行云流水ai笔记】粗粒度控制:推荐CTRL、GeDi 细粒度/多属性控制:推荐TOLE、GPT-4RL

TOLE模型完整启动方法指南 TOLE (Token-level Optimization with Language Models) 是一种基于强化学习的可控文本生成方法&#xff0c;通过token级别的反馈实现对文本多个属性的精确控制。以下是完整的启动方法指南&#xff1a; 1. 环境准备 1.1 创建虚拟环境 conda creat…

【沉浸式解决问题】idea开发中mapper类中突然找不到对应实体类

目录 一、问题描述二、场景还原三、原因分析四、解决方案 一、问题描述 mapper类继承了mybatis-plus的BaseMapper&#xff0c;泛型需要填入实体类&#xff0c;但是不知怎么地突然实体类就报错了&#xff0c;显示没有这个类 二、场景还原 实体类就是死活报错找不到&#xff0c;所…

初学python的我开始Leetcode题11-2

提示&#xff1a;100道LeetCode热题-11-1主要是二分查找相关&#xff0c;包括三题&#xff1a;搜索旋转排序数组、寻找旋转排序数组中的最小值、寻找两个正序数组的中位数。由于初学&#xff0c;所以我的代码部分仅供参考。前言上次的三道二分查找题较为基础&#xff0c;主要是…

Python 数据分析与可视化 Day 12 - 建模前准备与数据集拆分

✅ 今日目标 掌握建模前常见准备步骤学会使用 train_test_split() 将数据划分为训练集和测试集理解特征&#xff08;X&#xff09;与标签&#xff08;y&#xff09;的区分学习常见建模流程的输入要求&#xff08;格式、维度&#xff09;&#x1f4d8; 一、建模前准备流程概览 数…