2019CQU IOT RFID读写器实验-命令行实现读卡号卡类型、实现钱包的创建充值扣款等功能

2019CQU IOT RFID读写器实验-TYF于2022/04/23

系本人基于给定资源原创开发,实现了读写器读写IC卡,实现了读卡号卡类型、实现钱包的创建充值扣款,控制蜂鸣器状态、设置工作模式、查看读写器版本等功能–基于命令行实现
开发语言:C++
开发工具:visual studio C++
读写器:S50

项目地址

gitee: https://gitee.com/TangGarlic/CQU_RFID_2019.git

github: https://github.com/TonyTang-dev/CQU_RFID_2019.git

注意事项

  1. 此文及项目为TYF发出,仅供参考,声明本人实验报告并非抄袭(万一我老师以为我自己抄自己的博客嘿嘿)
  2. 拒绝任何形式的恶意篡改和恶意使用
  3. 倡导健康绿色的二次开发使用
  4. 本人声明,若有基于此代码的恶意行为皆与本人无关

实验过程或算法(源程序)

1、实验过程
1.1首先,分析需求,使用S50读写器和一张IC卡,一台计算机和开发工具visual studio C++;
1.2系统要求能够实现查询卡号,初始化钱包以及充值扣款等功能,要求在卡片接触时有蜂鸣器呼叫;
1.3综合上述要求:系统要能够实现查询功能,读写功能和控制蜂鸣器的功能,并在此基础上进行延伸;
1.4首先实现卡号查询功能,由于需要使用串口对象的地方较多,因此我将串口实例声明为指针,便于传参使用。读卡时,我们首先要向读写器写入命令,如读卡命令格式如下:

在这里插入图片描述

其为8字节的数据,因此我们在全局声明一个字节数组用来存储命令,以便于发送到读写器,通过CheckSumOut()函数来计算命令的校验和并写入到命令中,通过SerialPort->WriteData()函数将命令写入读写器中,再通过SerialPort->GetBytesInCOM()函数获取端口输入,在得到串行数据之后将其存入一个临时数组中,并检验返回数据的类型,如果返回数据成功则计算其校验和以检验数据正确性,通过Hex2Str()函数将字节流转化为字符流,通过对数据的解析获得卡数据和卡类型并显示到控制台上。最终查询卡号效果如下图:

在这里插入图片描述

1.5由于实验需要对IC卡的各个块号进行读写,所以先引入对数据块的操作,而后再进行“钱包”的创建操作;对数据块的操作方式与读卡号相类似,根据命令手册初始化对应的命令存入对应的命令格式中,计算校验和之后,将命令通过串口实例发送到下位机中,并获取返回的串口数据,解析得到对应的数据;写入数据与此同理。
1.6钱包操作:首先初始化钱包,这里我默认钱包的存储块号是8号,不提供用户自定义修改的接口,同时初始化钱包时,将钱包余额初始化为0;选取对应的命令发送给下位机;钱包充值:命令发送与上述同理,需要注意的是,钱包的余额存储方式为6-9字节以“低-高”的方式进行存储,而当前系统只提供用户十进制输入的类型,显然与用户输入的存储方式不一致,所以我对数据的处理是,充值数据以8字节存储,输入不满8字节时,在前方自动补0,这样就能很好的实现数据的写入和操作,实现算法如下:

在这里插入图片描述

1.7钱包扣款的实现与充值类似
1.8查询余额即发送对应命令,解析返回数据即可
1.9至此,钱包的操作实现完毕,将各类提示封装,提高用户可操作性。
1.10在此基础上,向系统添加了蜂鸣器状态控制、卡片检测、读写器工作模式设置,强制蜂鸣器蜂鸣和查看读写器版本以及关闭系统的功能;
1.11蜂鸣器状态控制:控制的主要是0x04类命令的状态,当设置为关闭时执行此类命令时蜂鸣器不会响起,反之则会蜂鸣,用户可通过选择功能并输入对应命令控制其状态;
1.12卡片检测:卡片检测是一直等待卡片进入读写器,如果读写器上没有卡片则不会有任何输出,反之则会输入卡片的类型和卡号,目前仅读一次,即卡片放到读写器上会读取一次便不会再读取,同时进过3秒延时之后会自动跳出监听状态进入主系统;
1.13读写器工作模式设置:当前仅实现了自动读卡号模式,当发送命令时,会将读写器的工作模式设置为自动读卡号,即当有卡片接触读写器,蜂鸣器会提示同时会返回卡片数据,由于其他模式的设置与此类似,故此系统暂时未实现其他命令;
1.14强制蜂鸣器蜂鸣:通过强制命令控制蜂鸣器长响和关闭其长响;
1.15查看读写器版本,通过发出对应命令,接受串口数据并解析得到读写器的版本号并显示到控制台上。
1.16最后,通过监听用户输入,当用户输入关闭命令时,通过系统函数exit()退出系统。
1.17至此,整个实验完毕,但系统还可继续扩展,首先与实验时间,本实验暂时到此。
系统主页效果:

在这里插入图片描述

1、源程序实现(主要部分)
由于源代码太长,这里展示读卡号源代码,其余部分见附录一

1 /// <summary>
2 /// 读卡号函数封装
3 /// </summary>
4 /// <param name="argc">串口对象:*mySerialPort</param>
5 /// <param name="argv"></param>
6 /// <returns>none</returns>
7 
8 void readIC(SerialPort *mySerialPort) {
9 	UCHAR inbyte;
10	UCHAR revdata[32];
11	UINT len = 0;
12	UINT readbytes;
13	CheckSumOut(CmdReadId, CmdReadId[1]);
14	mySerialPort->WriteData(CmdReadId, CmdReadId[1]);
15	Sleep(200);								// 延时200毫秒等待读写器返回数据,延时太小可能无法接收完整的数据包
16	len = mySerialPort->GetBytesInCOM();	//获取串口缓冲区中字节数
17	if (len >= 8)							// 读卡号读卡器返回的数据包长度:失败为8字节,成功为12字节
18	{
19		readbytes = 0;
20		do									// 获取串口缓冲区数据
21		{
22			inbyte = 0;
23			if (mySerialPort->ReadChar(inbyte) == true)
24			{
25				revdata[readbytes] = inbyte;
26				readbytes++;
27			}
28		} while (--len);
29		if ((revdata[0] = 0x01) && ((revdata[1] == 8) || (revdata[1] == 12)) && (revdata[1] == readbytes) && (revdata[2] == 0x0A1) && (revdata[3] = 0x20))
30		{
31			bool status = CheckSumIn(revdata, revdata[1]);
32			if (status)
33			{
34				if (revdata[4] == 0x00)
35				{
36					UCHAR cardtype[5];						//保存卡类型
37					UCHAR id[9];							//保存卡号
38					Hex2Str(&revdata[5], &cardtype[0], 2);	// 数组revdata[5]开始2字节为卡类型
39					Hex2Str(&revdata[7], &id[0], 4);		// 数组revdata[7]开始4字节为卡号
40					cout << "当前IC卡类型:" << cardtype << ",卡号:" << id << endl;
41				}
42				else
43				{
44					cout << "未检测到卡,将IC放置到读写器感情区才可读卡!" << endl;
45				}
46			}
47		}
48	}
49	else
50	{
51		cout << "读卡超时,请检查读卡器的连接是否正常!" << endl;
52		while (len > 0)
53		{
54			mySerialPort->ReadChar(inbyte);
55		}
56	}
57
58	return;
59}

实验结果及分析和(或)源程序调试过程

1、实验结果
1.1 实验功能完全实现,读写器接触卡则蜂鸣器响起,能够卡数据,初始化钱包和充值扣款功能得到完全实现并能正常工作,在此基础上实现了读写块数据,控制蜂鸣器,设置读写器工作状态和查看读写器版本等功能;
1.2 实现效果图
1.2.0 测试软件运行图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpGF2bSy-1650711761789)(resultImg/6.png)]

1.2.1 系统主页

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ENYYfTV1-1650711761791)(resultImg/7.png)]

1.2.2 启动系统监听卡片效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8j47NcV-1650711761793)(resultImg/8.png)]

1.2.3 初始化钱包,充值扣款效果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBT4Pbvl-1650711761796)(resultImg/9.png)]

1.2.4 自动检测效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rEKf6O4A-1650711761798)(resultImg/10.png)]

1.2.5 设置工作模式和设置蜂鸣模式和查看读写器版本效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7M3aM8X-1650711761800)(resultImg/11.png)]

1.2.6 退出系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YB1PgCyG-1650711761802)(resultImg/12.png)]

1.2.7 实物图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WwuCqK4Q-1650711761804)(resultImg/13.png)]

2、调试过程及所遇问题
2.1 问题
2.1.1 在读写块数据和获取充值金额时,总是出现数据解析错误,从而导致系统出现错误
原因分析:系统在获取输入时由于存在结尾字符,自动将字符串末尾填充NULL,导致解析错误,因此需要对输入数据遍历,并设置为初始值;
问题解决:对输入数据遍历,对控制符再初始化为初始值,因为此值是未使用的,更改不会对系统造成影响,问题得到解决。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qn0gzsJ9-1650711761806)(resultImg/14.png)]

2.1.2 在钱包的充值和扣款中,出现金额增减出错的问题
原因分析:IC卡存储金额的方式为“低-高”位的存储方式,如果不对用户输入进行格式化,则会出错,导致错误解析;
问题解决:对用户输入进行格式化,对输入的数据按照8字节的宽度使用前置补0,使其工作正常。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2YuzBpJN-1650711761808)(resultImg/15.png)]

3、调试过程
3.1.1 调试中,大部分的代码重复率高,导致出现大量冗余,因此后期将可复用代码封装为函数,增强系统底层代码的可复用性。
3.1.2 由于大部分命令具有可复用性,即大部分命令的长度和格式都相类似,因此特地声明全局的命令格式数组,可在不同阶段,根据需求修改命令格式,进而实现相应效果,如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kWpfzfmV-1650711761809)(resultImg/16.png)]

至此,实验完成

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值