基于51单片机的WiFi-rfid的图书馆借书还书图书管理系统

随着时代的快速进步,学习的文化愈加发达,知识经济现象也日益显著,各种图书馆已成为咨询服务的常去之地。而由于图书种类繁多、数量巨大、借阅周转快捷等各大现象困扰着工作人员。RFID图书智能管理技术是采用了自动识别技术和无线电射频通信技术,非接触式的自动识别技术。近几年RFID技术已经引起了成为了图书馆的关注之星。RFID图书管理技术让阅读更轻松!

RFID“智能馆藏系统”包含了馆员服务系统、芯片转换系统、自助借书系统、自助还书系统、 馆藏盘查系统、通道侦查系统等一系列自动化管理系统。每一本图书都贴上RFID标签,RFID检查机被安装在图书馆的出口处。当有人离开图书馆时携带没有被检查的贴着RFID标签的图书或其他媒体资料时,RFID检查机就会响起警报。如果有人试图避开警报带走书籍的话,图书馆仍然可以追踪图书, 从而将其归放在原处。

本系统采用STC89C52单片机作为主控芯片,液晶12864作为人机交互界面,采用非接触式RC522作为RFID电子标签检测模块,编写电脑上位机图书管理软件数据库单片机和上位机软件通过TCP协议的wifi连接的通信方式实现数据传输,上位机可以录入图书信息包括了书名、作者、出版社,还可以对图书进行修改编辑、删除、查询等功能通过编写上位机软件图书管理系统软件、单片机源代码、设计硬件电路,最后做出一套基于单片机RFID电子标签图书管理系统

关键字:STC89C52;RFID;电子标签;图书管理系统;

1绪论

RFID ( Radio Frequency Identification) 即无线射频识别技术, 是一种综合了自动识别技术和无线电射频通信技术的应用技术, 是一项非接触的自动识别技术。近几年 RFID 已经引起了国内外图书馆的关注。

RFID 主要由电子标签( Tag)、 读写器( Reader)和相关应用系统(Application System)所组成。RFID是一种应用电磁波频谱, 以非接触、 无视觉、 高可靠的方式, 传递特定识别信息的网络系统。RFID系统在图书馆管理领域的应用, 更新了传统的条码技术和安全机制, 加速了图书馆管理自动化的进程, 也为数字图书馆的建设提供了硬件平台。

电子标签又称射频标签、应答器、数据载体;阅读器又称为读出装置、扫描器、读头、通信器、读写器(取决于电子标签是否可以无线改写数据)。电子标签与阅读器之间通过耦合元件实现射频信号的空间(无接触)耦合;在耦合通道内,根据时序关系,实现能量的传递和数据交换。电子标签实际上就是属于RFID射频技术的一种。

电子标签具有以下优点

(1)可靠性高

电子标签与读写设备之间无机械接触,避免了由于接触读写而产生的各种故障;非接触式电子标签表面无裸露的芯片,无芯片脱落、静电击穿、弯曲损坏等问狻?

(2)使用寿命长

M1卡可以重复写次数为100,000次,读操作次数无限;

(3)操作方便、快捷

M1卡片使用没有方向性,无需插拔,大大提高每次使用的速度;

M1卡操作能源供应采用无源方式,非接触下操作;

(4)防冲突

非接触式卡M1中有快速防冲突机制,能防止卡片之间出现数据干扰。因此,读写器可以“同时”处理多张非接触式IC卡,提高了应用的并行性。

(5)可以适用多种应用

非接触式卡M1的分扇区、分块的存储器结构特点使它适用于一卡多用,能应用于不同的系统管理,可根据不同的应用设定不同的密码和访问条件。

(6)加密性能好

非接触式卡M1的有不可更改的全球的芯片唯一序列号;非接触式卡与读写器之间采用双向验证机制,非接触式卡M1在数据处理前要与读写器进行三次相互认证,而且在通讯过程中所有的数据都加密;

RFID的电子标签较条码有更多的优越性:

资料可更新: 条码印刷之后就无法更改,RFID电子标签则可不限制次数的新增、修改、删除其标签内存储的资料。

方便资料辨读: 条码阅读器在近距离而且没有物体阻挡下,要使扫描光源照射在条码上才能辨读,RFID标签只要在无线电波范围内,即可传送信号。

存储资料容量大: 一维条码是50字节,二维条码最大的容量可储存2至3000字节;RFID标签最大容量可以达到数兆字节。

可重复使用: 条码随着商品的寿命结束而结束;RFID标签因为本身资料可更新,因此可以重复使用。

扫描速度快:可同时读取数个资料,条码阅读器一次只能读取单一条码资料;RFID标签的辨识器可同时间辨识多个标签。

安全性好: RFID标签读取方面皆有密码保护,高度安全性的保护措施使之不易被伪造。

耐久性: 一般传统纸制或塑胶材质的条码有时会因下雨或潮湿的环境及搬运的过程中遭致毁损而难辨识。RFID具有重复使用数十万甚至数百万次以上的特性, 其材质也能够被放置于较为恶劣的环境中,因此比条码更有耐久性,自然成本 也较为节省。

体积小: 传统的磁性条码受限于体积,不易嵌在较小的物品上。RFID则不然,它的迷你体积可以隐藏在各种物品里面。

1 硬件部分设计

1.1 单片机主芯片

89C52单片机是51系列单片机的一个成员,是8051单片机的简化版内部自带2K字节可编程FLASH存储器的低电压、高性能COMS八位微处理器,与IntelMCS-51系列单片机的指令和输出管脚相兼容。由于将多功能八位CPU和闪速存储器结合在单个芯片中,因此,89C52构成的单片机系统是具有结构最简单、造价最低廉、效率最高的微控制系统,省去了外部的RAM、ROM和接口器件,减少了硬件开销,节省了成本,提高了系统的性价比,具有以下主要特点:

1. 增强型8051单片机,6 时钟/机器周期和12 时钟/机器周期可以任意 选择,指令代码完全兼容传统8051

2. 工作电压:5.5V~3.3V(5V单片机)/3.8V~2.0V(3V 单片机)

3.工作频率范围:0~40MHz,相当于普通8051 的0~80MHz,实际工作 频率可达48MHz

4. 用户应用程序空间为8K字节

5. 片上集成512 字节RAM

6. 通用I/O 口(32 个),复位后为:P0/P1/P2/P3 是准双向口/弱上拉, P0 口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为 I/O 口用时,需加上拉电阻。

7. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程序,数秒即可完成一片

8. 具有EEPROM 功能

9. 共3 个16 位定时器/计数器。即定时器T0、T1、T2

10.外部中断4 路,下降沿中断或低电平触发电路,Power Down 模式可 由外部中断低电平触发中断方式唤醒

11. 通用异步串行口(UART),还可用定时器软件实现多个UART

12. 工作温度范围:-40~+85℃(工业级)/0~75℃(商业级)

13. PDIP封装

本系统采用的STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有 8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案STC89C52RC各个引脚的定义

VCC/GND:供电电源。

P0口:可以被定义为数据/地址的低八位,能够用于外部程序/数据存储器。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:标准输入输出 I/O,P1口管脚写入1后,被内部上拉为高,可用作输入。在FLASH编程和校验时,P1口作为第八位地址接收。

P2口:既可用于标准输入输出I/O,也可用于外部程序储存器或数据存储器访问时的高八位地址。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:既可以作标准输入输出I/O,也可作为一些特殊功能口, 管脚备选功能:
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中断0)
P3.3 /INT1(外部中断1)
P3.4 T0(记时器0外部输入)
P3.5 T1(记时器1外部输入)
P3.6 /WR(外部数据存储器写选通)
P3.7 /RD(外部数据存储器读选通)
RST:复位当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部储存器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。

/PSEN:外部程序储存器的选通信号。在由外部程序储存器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加5V编程电源。
XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:来自反向振荡器的输出。

STC89C52RC单片机

1.2单片机最小系统

1.2.1复位电路

复位电路的功能就是对CPU进行实时监测,当CPU落入死循环之后,能及时发现并使整个系统复位。为确保微机系统中电路稳未定可靠工作,复位可靠工作,复位电路是必不可少的一部分,复位电路的第一功能是上电复位。一般微机电路正常工作需要供电电源为4.75〜5.25V。由于微机电路是时序数字电路,它需要稳定的时钟信号,因此在电源上电时,只有当VCC上电时,只有VCC超过4.75V,低于5.25V以及晶体振荡器稳定工作时,复位信号才被撤除,微机电路开始正常工作。

为了确保本设计系统中的电路能够可靠、稳定的工作,复位电路是必不可少的一部分。复位电路是一种能够让电路恢复到起始状态的电路设备,原理类似于计算机的重启按键。如果主板上没有ISA总线,也就是8XX系列芯片组的主板,IDE的复位直接来自于南桥,在两者之间通常也会有一个非门或是反向电子开关,PCI总线的复位就直接来自于南桥,有些主板会在两者之间加一个跟随器,跟随器起缓冲延时作用。且PCI的常态为3.3V 或5V,复位时为0V,AGP总线的复位信号和PCI总线的复位信号是同路产生的。也有的主板AGP总线的复位也是由南桥直接供给的,常态时为高电频,复位时为低电频,对于北桥的复位信号也是和PCI总线的复位信号同时产生,也就是说PCI总线的复位信号,AGP总线的复位信号和北桥的复位信号通常是串在一根线上的,复位信号都相同,对于CPU的复位信号,不同的主板都是由北桥供给,I/O的复位信号是由南桥直接供给,通常是3.3V或5V。一般来说51单片机复位电路电路图如图所示。

复位电路电路图

本设计中复位电路与单片机的9引脚(RST)相连接,负责单片机的复位工作。本设计中复位电路的供电电压为5V。当给复位电路5V电压时,电容充电,在1K欧姆电阻R1上出现电压,使得单片机复位。几个毫秒之后,电容充满电,1K欧姆电阻R1上的电流为0A,同时电压也为0V,使得单片机进入工作状态。在单片机工作期间,按下开关S1,电容放电,在1K欧姆电阻R1上出现电压,使单片机复位。松开开关S1,电容又开始充电,在几个毫秒之后,单片机进入工作状态。本系统采用上电复位,因此在电路设计过程中没有手动按键复位。

 1.2.2 晶振电路

晶振全名叫做晶体振荡器,它结合内部电路产生所需的时钟频率,晶振所提供的时钟频率越高,单片机运行速度就越快。晶振的作用是提供本的时钟信号,使各部分保持同步进行。晶振通常与锁相环电路互相配合使用,以提供所需的时钟频率。单片机的一切指令的执行都是建立在这个基础上的,晶振的提供的时钟频率越高,那单片机的运行速度也就越快。

振荡电路(时钟电路)的主要任务是为C51单片机正常工作需要的时钟电路提供一个稳定的工作频率。晶振回路由电容和陶瓷谐振器并联组成,作为单片机的时钟源。C51内部有一个用于构成振荡器的高增益反相放大器,此放大器的输入和输出端分别是引脚XTAL1XTAL2,在XTAL1XTAL2端口接上时钟电源即可构成时钟电路。本设计中采用内部时钟产生方式。在XTAL1和XTAL2两端跨接晶振,与内部的反相器构成稳定的自激振荡器。其发出的时钟脉冲直接送入单片机内定时控制部件。电容应尽可能的安装在单片机芯片附近,以减少寄生电容,保证振荡器稳定可靠的工作。

晶振用一种能把电能和机械能相互转化的晶体在共振的状态下工作,以提供稳定,精确的单频振荡。在通常工作条件下,普通的晶振频率绝对精度可达百万分之五十。高级的精度更高。有些晶振还可以由外加电压在一定范围内调整频率,称为压控振荡器(VCO)。晶振的作用是为系统提供基本的时钟信号。晶振通常与锁相环电路配合使用,以提供系统所需的时钟频率。如果不同子系统需要不同频率的时钟信号,可以用与同一个晶振相连的不同锁相环来提供。在本设计中的晶振电路由一个晶振片Y1和两个22pF的电容C1、C2组成,晶振电路与STC89C52单片机的18引脚和19引脚相连接,以便提供单片机工作所需的时钟频率51单片机的晶振多采用12MHZ或者11.0592MHZ的频率。晶振电路电路图如图所示。

1.3 LED电路

发光二极管与普通二极管一样是由一个PN结组成,也具有单向导电性。当给发光二极管加上正向电压后,从P区注入到N区的空穴和由N区注入到P区的电子,在PN结附近数微米内分别与N区的电子和P区的空穴复合,产生自发辐射的荧光。不同的半导体材料中电子和空穴所处的能量状态不同。当电子和空穴复合时释放出的能量多少不同,释放出的能量越多,则发出的光的波长越短。常用的是发红光、绿光或黄光的二极管。发光二极管的反向击穿电压大于5伏。它的正向伏安特性曲线很陡,使用时必须串联限流电阻以控制通过二极管的电流。发光二极管的核心部分是由P型半导和N型半导体组成的晶片,在P型半导体和N型半导体之间有一个过渡层,称为PN结。在某些半导体材料的PN结中,注入的少数载流子与多数载流子复合时会把多余的能量以光的形式释放出来,从而把电能直接转换为光能。PN结加反向电压,少数载流子难以注入,故不发光。当它处于正向工作状态时(即两端加上正向电压),电流从LED阳极流向阴极时,半导体晶体就发出从紫外到红外不同颜色的光线,光的强弱与电流有关。

LED灯的最基本的原理就是半导体二极管,将电转化为光。一般的LED都会采用注式电致原理制作,通常认为是发光二极管,也就是LED灯。

LED灯实物图

LED作为电子电路中最常用的指示作用,LED作为二极管的一个最典型元件,其两端也是有一个压降,一般1.3V左右,根据电子知识,只要在两端上有超过这个的压降,二极管就导通,为了保险起见,可以在单片机的IO口接上一个限流电阻,不至于上电时容易烧坏。例如当单片机的P35低电平的时候,LED灯就亮,反过来,当为高电平的时候,LED灯就灭。

LED驱动电路

1.4蜂鸣器电路

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“ZZG”、“LB”、“JD”等)表示。蜂鸣器的发声原理由振动装置和谐振装置组成,而蜂鸣器又分为无源他激型与有源自激型。首先大家要了解有源和无源这里的“源”不是指电源,而是指震荡源。也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它。有源蜂鸣器往往比无源的贵,就是因为里面多个震荡电路。无源他激型蜂鸣器的工作发声原理是:方波信号输入谐振装置转换为声音信号输出有源自激型蜂鸣器的工作发声原理是:直流电源输入经过振荡系统的放大取样电路在谐振装置作用下产生声音信号

采用的是直流电压5V供电的有源蜂鸣器,但是一般的蜂鸣器在整个系统运行中需要比较大的电流,51单片机的IO口除了P0口外其他的都有一个弱上拉电阻,但IO的驱动电流也是非常低,不加外部的驱动电路是很难直接驱动的。而最常用的就是用普通的三极管来放大电流驱动,该三极管在电路中的作用是开关电路并且放大电流,本设计中采用三极管S8550作为驱动,当P37电平时,三极管导通,蜂鸣器响;当P37高电平时,三极管截止,蜂鸣器不响。报警提醒电路如图所示。

蜂鸣器驱动电路

1.5 按键电路

通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动.按键稳定闭合时间长短是由操作人员决定的,通常都会在100ms以上,刻意快速按的话能达到40-50ms左右,很难再低了。抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。

设计中有注册卡片、注销卡片等功能,这些功能的切换都是通过按键来实现的,按键一般有独立按键,矩阵键盘等,由于本次涉及到的按键不需要很多个,因此采用独立按键的形式,简单方便易操作,而按键电路用的是直接练到单片机的IO上面,通过对该IO口电平读取不同的值来区别按下还是弹开。采用的是机械式按键,所以在按下的过程中会有电压毛刺干扰,为了防止误触发按键,一般电路中加入消抖处理,有硬件消抖和软件消抖,考虑到简单实用,本设计采用10MS的延时来代替消抖动作。

按键输入电路

1.6 液晶显示电路

液晶显示模块是面向用户界面的,所以需要充分显示所要表达的内容,还要简洁,所以本系统采用的液晶显示模块为QC12864B,这个模块带有中文字库,不需要用户自己定义,只需要定义好位置显示即可,能够显示的汉字有32个,一个汉字相当于两个字符,所以,字符可以显示64个。LCD12864液晶显示模块共有20个引脚,通讯方式有串口和并口两种,串行可以用SID口通讯,并口是有8个数据口,实现8位并口传输。液晶的引脚图如下图所示。液晶的D0~D7是数据引脚,当液晶作为并行通信的时候,单片机要连接这8个数据口,而液晶的PSB引脚是选择并行或者串行的引脚,当低电平时为串行方式,当高电平时为并行方式。由于串口方式接口更简单,和单片机通信只需要2个IO口,在电路图设计中更为方便,所以一般在设计中可选择该方式。液晶还带了一个背光的对比度调节电位器,可以调节字体和背光之间的一个对比度,而现在很多液晶都已经出厂时就把这个电阻值定好了,无需在手动去调节

12864引脚图

液晶12864可以显示4行,每一行可以显示8个汉字,共可以显示32个汉字,对应这个系统来说,是足够的,一般出现不够行的情况下,大都是采用切换到第二个节目显示的方法;12864液晶跟单片机的通信方式有两种,一种是并行 ,一种是串行,对于串行来说,电路是比较简单不需要那么多的IO口,只需要两个IO就行,一发一收,但速率就比并行比较慢,而并行由于8个IO一起发送数据,因此要比较快,对于显示刷新频率要求不高的话,可以考虑用串行方式,毕竟电路简单,IO少,而本次的设计过程中采用的是串行行方式,跟LCD液晶的通信端只需要用到2个IO口,简单方便。

液晶屏驱动电路图

1.7 RC522通信电路

MF RC522是应用于13.56MHz非接触式通信中高集成度的读写卡芯片,是NXP公司针对“三表”应用推出的一款低电压、低成本、体积小的非接触式读写 卡芯片,是智能仪表和便携式手持设备研发的较好选择。 MF RC522利用了先进的调制和解调概念,完全集成了在13.56MHz下所有类型的被动非接触式通信方式和协议。支持14443A兼容应答器信号。数字部 分处理ISO14443A帧和错误检测。此外,还支持快速CRYPTO1加密算法,用语验证MIFARE系列产品。MFRC522支持MIFARE系列更 高速的非接触式通信,双向数据传输速率高达424kbit/s。 作为13.56MHz高集成度读写卡系列芯片家族的新成员,MF RC522与MF RC500和MF RC530有不少相似之处,同时也具备许多特点和差异。它与主机间通信采用UART模式,有利于减少连线,缩小PCB板体积,降低成本。

工作电流:13—26mA/直流3.3V
空闲电流:10-13mA/直流3.3V
休眠电流:<80uA
峰值电流:<30mA
工作频率:13.56MHz

支持的卡类型:mifare1 S50、mifare1 S70、mifare UltraLight、mifare Pro、mifare Desfire
产品物理特性:尺寸:40mm×60mm
环境工作温度:摄氏-20—80度
环境储存温度:摄氏-40—85度
环境相对湿度:相对湿度5%—95%

本设计中采用的非接触式刷卡模块RC522,该模块采用的供电电压是3.3V,和单片机通信的是SPI接口,用到了单片机的5个IO口,模块的IRQ中断引脚没有用到。单片机要对卡片进行操作必须和RC522模块完成个步骤,分别是寻卡,防冲突,选卡,读写操作。

RC522通信电路

1.8 DS3231时间电路

DS3231是低成本、高精度I2C实时时钟(RTC),具有集成的温补晶振(TCXO)和晶体。该器件包含电池输入端,断开主电源时仍可保持精确的计时。集成晶振提高了器件的长期精确度,并减少了生产线的元件数量。DS3231提供商用级和工业级温度范围,采用16引脚300mil的SO封装。

DS3231电源控制功能由温度补偿电压基准(VPF)和监视VCC电平的比较器电路提供。当VCC高于VPF时,DS3231由VCC供电,当VCC低于VPF但高于VBAT时,DS3231由VCC供电;当VCC低于VPF并低于VBAT时,DS3231由VBAT供电。为保护电池,VBAT首次加到器件时振荡器并不启动,除非加载VCC,或者向器件写入一个有效的I2C地址。典型的振荡器启动时间在1 s以内。在VCC加电后或者有效的I2C地址写入后大约2 s,器件会测量一次温度,并使用计算的修正值校准振荡器。一旦振荡器运行,只要电源(VCC或者VBAT)有效就会一直保持工作状态。器件每隔64 s进行一次温度测量并校准振荡器频率。

内部结构图

RTC保存秒、分、时、星期、日期、月和年信息。少于31天的月份,将自动调整月末的日期,包括闰年的修正。时钟的工作格式可以是24小时或带/AM/PM指示的12小时格式。提供两个可设置的日历闹钟和一个可设置的方波输出。地址与数据通过I2C双向总线串行传输。精密的、经过温度补偿的电压基准和比较器电路用来监视VCC状态,检测电源故障,提供复位输出,并在必要时自动切换到备份电源。另外,/RST监视引脚可以作为产生复位的手动输入。除计时精度高之外,DS3231还具有一些其它功能,这些功能扩展了系统主机的附加功能和选择范围。该器件内部集成了一个非常精确的数字温度传感器,可通过I2C*接口对其进行访问(如同时间一样)。这个温度传感器的精度为±3°C。片上控制电路可实现自动电源检测,并管理主电源和备用电源(即低压电池)之间的电源切换。如果主电源掉电,该器件仍可继续提供精确的计时和温度,性能不受影响。当主电源重新加电或电压值返回到容许范围内时,片上复位功能可用来重新启动系统微处理器。DS323l的引脚功能

1、32 kHz是32 kHz频率输出;

2、VCC用于主电源的DC引脚;

3、/INT/SQW为低电平有效中断或方波输出:是低电平有效复位引脚;

4~8、N.C.表示无连接,外部必须接地;

13、GND为地;

14、VBAT为备用电源输入;

15、SDA为串行数据输入、输出;

16、SCL为串行时钟输入。

DS3231电路

1.9 wifi电路

本系统加入了上位机功能,上位机和单片机通信,用的是wifi协议,因此在板子上加入了一个wifi串口模块,该模块已经内置了wifi协议,采用的是串口透传模式,即wifi模块和单片机通信,无需去关心wifi协议,完全按照串口通信协议开发即可,简单方便,因此本系统才有的是wifi串口透传模块,型号为DT-06,和单片机串口1通信,所以wifi模块的串口引脚接在单片机的串口1引脚,即P30、P31。

WIFI模块DT-06实物图

 软件部分设计

2.1 Keil软件介绍

Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。运行Keil软件需要WIN98、NT、WIN2000、WINXP等操作系统。Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil的优势。

C51工具包的整体结构,μVision与Ishell分别是C51 for Windows 和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。然后分别由C51及C51编译器编译生成目标文件(.obj)。目标文件可由LIB51 创建生成库文件,也可以与库文件一起经L51 连接定位生成绝对目标文件(.abs)。abs文件由OH51 转换成标准的hex 文件,以供调试器dScope51 或tScope51 使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。

Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil的优势。C51工具包的整体结构,μVision与Ishell分别是C51 for Windows 和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。然后分别由C51及C51编译器编译生成目标文件(.obj)。目标文件可由LIB51 创建生成库文件,也可以与库文件一起经L51 连接定位生成绝对目标文件(.abs)。abs文件由OH51 转换成标准的hex 文件,以供调试器dScope51 或tScope51 使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。

2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。新版本支持更多最新的ARM芯片,还添加一些其他新功能。

2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil μVision4,其编译器、调试工具实现与ARM器件的最完美匹配。

Keil4软件开启界面

2.2 Altium Designer软件

Altium Designer 是原Protel软件开发商Altium公司推出的一体化的电子产品开发系统,主要运行在Windows操作系统。这套软件通过把原理图设计、电路仿真、PCB绘制编辑、拓扑逻辑自动布线、信号完整性分析和设计输出等技术的完美融合,为设计者提供了全新的设计解决方案,使设计者可以轻松进行设计,熟练使用这一软件使电路设计的质量和效率大大提高电路设计自动化 EDA(Electronic Design Automation)指的就是将电路设计中各种工作交由计算机来协助完成。如电路原理图(Schematic)的绘制、印刷电路板(PCB)文件的制作、执行电路仿真(Simulation)等设计工作。随着电子科技的蓬勃发展,新型元器件层出不穷,电子线路变得越来越复杂,电路的设计工作已经无法单纯依靠手工来完成,电子线路计算机辅助设计已经成为必然趋势,越来越多的设计人员使用快捷、高效的CAD设计软件来进行辅助电路原理图、印制电路板图的设计,打印各种报表。

Altium Designer 除了全面继承包括Protel 99SE、Protel DXP在内的先前一系列版本的功能和优点外,还增加了许多改进和很多高端功能。该平台拓宽了板级设计的传统界面,全面集成了FPGA设计功能和SOPC设计实现功能,从而允许工程设计人员能将系统设计中的FPGA与PCB设计及嵌入式设计集成在一起。 由于Altium Designer 在继承先前Protel软件功能的基础上,综合了FPGA设计和嵌入式系统软件设计功能,Altium Designer 对计算机的系统需求比先前的版本要高一些。

Altium Designer Summer 09的发布延续了连续不断的新特性和新技术的应用过程。这必将帮助用户更轻松地创建下一代电子设计。同时,我们将令Altium Designer更符合电子设计师的要求。Altium的一体化设计结构将硬件、软件和可编程硬件集合在一个单一的环境中,这将令用户自由地探索新的设计构想。在整个设计构成中,每个人都使用同一个设计界面。 Summer 09版本解决了大量历史遗留的工具问题。其中就包括了增加更多的机械层设置、增强的原理图网络类定义。新版本中更关注于改进测试点的分配和管理、精简嵌入式软件开发、软设计中智能化调试和流畅的License管理等功能。

Altium Designer 09 软件

2.3 STC-ISP下载器

STC-ISP 是一款单片机下载编程烧录软件,是针对STC系列单片机而设计的,可下载STC89系列、12C2052系列和12C5410等系列的STC单片机,使用简便,现已被广泛使用。一般采用以下步骤来下载程序到51单片机:

  1. 选择单片机对应的型号;
  2. 加载要下载程序对应的HEX文件;
  3. 选择硬件串口号;
  4. 设置串口波特率;
  5. 开始下载编程;

STC-ISP软件

2.4 visual studio 2012软件

Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。

Visual Studio 2012作为一个集成解决方案,适用于无论是个人或者各种规模的开发团队。Visual Studio 2012实现了同事间的无缝协作,提高了生产效率与专注度,最终好的点子变成了优秀的现实应用。

Visual Studio 2012荣获在软件界有奥斯卡奖之称的Jolt奖2013年生产力奖。Visual Studio已经逐渐将软件行业扩展到软件设计和协作、 生命周期,以及更改管理系统等方面,Visual Studio 2012版本提供了更为简便优化界面,实现轻松导航项目应用程序;加入了针对Windows 8项目的可视化的工具集,对于Web 开发,增加了最新的模板、工具以及对HTML5 和 CSS3等新标准的全面支持等。

2.5系统方案     

以STC89C52单片机为核心器件,结合按键电路、RC522模块、液晶显示屏、声光报警电路、时间模块电路、电脑上位机软件,利用单片机灵活的编程设计和丰富的I/O端口,及其控制的准确性通过软件程序来控制整个系统实现考勤系统的以下基本功能: 

  1. 上位机软件可以录入图书信息;
  2. 上位机软件可以对图书信息进行修改编辑;
  3. 上位机软件可以对图书进行删除;
  4. 上位机软件可以一键导入全部图书表;
  5. 单片机可以对电子标签进行识别检测;
  6. 单片机对无效的电子标签识别检测时需要有一定的报警提示;
  7. 硬件板子可以进行图书的借书功能;
  8. 硬件板子可以进行图书的还书功能;
  9. 单片机可以实时显示时间信息;
  10. 可以对系统时间进行校准;

系统方框图

2.6工作原理介绍

本文是需要做出一套软件和硬件相结合的软硬件全套系统,而且需要经过编写代码,画电路图,调试,焊接,等一系列过程,最后做出一个成品。所以本次中的软件部分也是其他一个重要点。本文的软件部分只用到单片机的编程,而没有用到其他的数据和上位机程序,所以相对来说比较简单。主要就是对51单片机进行C语言编程。本文中采用的是模块化编程,即是把全部的程序分为几个模块,一个模块对应一个C文件,这样的好处是简洁明了,调试方便,软件部分大概可分为主程序模块、液晶显示模块、刷卡模块、按键扫描模块、数据库存储模块、时间模块、wifi模块

2.6.1 注册流程

2.6.2 注销流程

2.6.3 DS3231写数据流程

2.6.4 DS3231读数据流程

2.6.5 按键输入流程

2.6.6 创建图书流程

2.6.7 标签识别流程

2.6.8 液晶屏流程

液晶显示模块选用QC12864B型号,它是一个完整的模块,只需要对其发布指令便可以完成相应的工作。LCD12864液晶模块内涵字库和处理器,具有自己的一套指令系统,用户只需要根据使用手册给出的指令系统,依照规定的指令格式,给模块发送指令,完成相应的功能。因为模块是带字库的,所以用户不需要自己定义字形,只需要设定好显示字符的坐标,再将字符发送过去即可。发送汉字时,因为是双字节,所以要先发送高字节,再发送低字节。并且当单片机向模块发送指令之前,需要检查模块是否处于忙状态,也就是需要读取BF标志位,当标志位为0时才能够发送新的指令。如果不想判断忙碌状态,就需要在发送指令之前先延时足够长的一段时间,确保上一条指令发送完毕。

2.7上位机介绍

电脑上位机软件是用C++语言开发的,开发工具用的是visual studio 2012,电脑上位机软件和单片机通信的方式是wifi连接,界面如下图所示。

功能主界面

上位机软件首先要将本电脑的wifi网络连接到wifi模块的热点,以便电脑端和wifi服务器端处于同一个局域网络下,再打开上位机软件,点击连接设备按钮,连接成功后即可进行数据通信。上位机可以新建图书信息、修改编辑图书信息、删除图书,还可以通过书名、作者、出版社等关键词进行查找图书,上位机软件也可以一键导入全部图书功能。

通过书名查找图书

一键导入全部图书

连接设备提示

3 调试与实现

3.1 调试遇到的问题

板子焊接好后,就要对单片机烧写程序,开始验证各个软件和硬件的部分,而本次中事实上不是一下就成功的,也遇了不少的问题,下面就对在调试过程中遇到的问题阐述说明:

1、无法下载程序

把电路基本焊接完成后,首先接上电源,用万用表量电压正常,接上USB转TTL模块,将电脑端的TXD、RXD和单片机的P31、P30相连,开始下载程序,发现一直没反应,最后发现是没有共地造成的,电脑和单片机板子共地之后正常下载;

2、按键不灵敏

板子上有个独立按键,有各自的功能,在测试中,发现所有的按键都不太灵敏,当按下录入按键时,本来液晶是显示提示正在注册卡片,但结果液晶一直没正常的显示,或者有时显示,硬件实在找不出问题后转向软件问题,最后发现按键消抖延时,长得太离谱,导致要一直按着按键才有反应,改短了时间为10ms,按键也正常反应。

3、液晶不显示

本次采用的是液晶12864作为显示器,采用的是串口接法,只需要用到单片机的2个IO口,方便简单,在调试过程中,发现液晶无法显示出文字信息,只亮了背光,把一样的程序烧到另外一个开发板上面,开发板上面的液晶正常显示,验证了是焊接的板子问题,再次将开发板上面的液晶换到焊接的板子上面,液晶也正常显示,由此可见,就是液晶本身的问题。想起液晶有串行和并行两种接口,咨询了卖家之后才得知,这一块液晶是并口接口的,想要换成串行接法,须将液晶背面的一个电阻焊掉,焊掉该电阻之后,重新插上液晶,正常显示。

4、蜂鸣器不响

刷卡成功通过之后,蜂鸣器会嘀的一声,同时绿灯亮,但是在最后是实物调试中,绿灯亮了但是蜂鸣器没有响,一开始以为蜂鸣器烧坏了,拆了之后重新焊接一个新的,依然还是不工作;检查三极管的极性也是没有接反,最后发现是三极管的型号错了,焊接的是S8050,而S8550是PNP的,S8050是NPN的,按照设计的电路,S8050是无法驱动的,换了三极管型号之后,蜂鸣器正常工作。

总结

本设计论文主要介绍了基于单片机电子标签图书管理系统的软件和硬件为一体的一整套系统,通过搜集资料,购买元器件,编程单片机源程序,设计各个电路模块,到最后对每个模块进行软件和硬件的调试,到最后整个硬件系统的组装,通过自己的努力和同学老师们的帮助,最后完成了这套软件和硬件相结合的实物系统,从我自身的观点去看,还是觉得挺成功的,毕竟从0基础开始学起,包括编写单片机的程序到画电路图,焊接板子,调试板子,查找问题,历经几个月的时间,总算还是有收获的,但是作为这样的一个设计,本身存在的问题也是很多的,在调试的过程中也确实遇到了不少的麻烦,比如一开始程序无法下载,液晶一直无法显示,以及焊接过程中烧坏LED等等,而在本次的设计过程中,对于射频的基本算法了解的还是比较少,没有具体的深入去研究这个方面的理论知识,而是直接从和单片机如何进行通信,如果对卡片进行编程实现的这一方面去着手,所以对于这方面做得还不算很好,还有很多可改进的地方,但是在这过程中,也需要硬件电路还有通信方式以及数据的处理这些,,还是自己可以学的到的,也从这个实践中更能够跟理论知识结合起来。

通过此次毕业设计,锻炼我的动手能力,深切体会到了理论和实际的差距,在通过写程序,还有对程序的编译调试过程中,能够检查差好多错误,通过分析这些错误产生的原因,让我的编程能力得到很大的提高,在解答这些问题之中,可以体会到问题解决的成就感,让我对单片机智能控制这一方面产生了浓厚的兴趣,以后我会继续在这方面学习,下苦功夫,争取在这个方面更上一个台阶。

由于自身水平有限,设计中一定存在很多不足之处,敬请各位老师批评指正。

参考文献

[1]康华光.电子技术基础模拟部分[M].(第四版).北京:高等教育出版社,1999.

[2]谭浩强.C语言设计[M].(第三版).清华大学出版社,2005.

[3]郭天祥.新概念51单片机C语言教程[M].电子工业出版社,2009.

[4]谢自美.电子线路设计•实验•测试[M].(第三版).武汉:华中科技大学出版 社,2006.

[5]樊昌信 曹丽娜.通信原理[M].(第六版).北京:国防工业出版社,2009.

[6]全国大学生电子设计竞赛组委会编.全国大学生电子设计竞赛[M].北京理工 大学出 版社,1999.

[7]郁有文 常健 程继红.传感器原理及工程应用[M].(第二版).武汉:西安电子 科技大 学出版社,2006.

[8]崔炳哲.电子控制入门[M].北京:科学出版社,2003.

[9]郁有文 常健 程继红.传感器原理及工程应用[M].(第二版).武汉:西安电子 科技大 学出版社,2006.

[10]郭海英.基于单片机的电子安全密码锁的设计[M].现代电子技术,2005,(13)

致谢

时间不等人,一眨眼的功夫,几个月就过去了,毕业设计和毕业论文也在此刻接近尾声,而这也意味着我的大学生活即将结束,告别学校,走向社会。看着桌面放着的毕业设计,心里还是挺欣慰的,毕竟是自己辛辛苦苦的劳动成果,也是对大学生涯的一个交代,心里不得还是比较开心高兴的。在设计的过程中或多或少肯定遇到了不少的难题,设计到硬件部分还有软件部分,编写程序,画电路图,动手焊接电路板,安装调试。遇到的问题不懂的都是自己先去查找资料,上网百度,上图书馆查阅,向身边的同学,高年级的师兄师姐请教,当然还有向指导老师请教,真的很感谢他们对我的帮助,毫无保留,在这过程中,学到的东西还是很多的,毕竟平时学到的都是一些最基本的理论知识,实际动手做实验还是比较少的,最后在自己和同学们的帮助下还是很惊喜的完成了属于我自己的毕业设计和论文撰写。在这次的设计过程中,从最初对单片机的各种理论知识的简单了解,C语言程序的看不懂,焊接电路的无法上手,各种各样的问题克服,体会到真正动手去实际的意义,以前总是死记硬背的去记各种知识,但是在实际应用中还是比较少的,在实际中去找问题,解决问题,更为实际。而在本次毕设中,也让我懂得了一个道理,凡事都要有耐心,要善于运用学到的知识来验证问题,有问题肯定是正常的,但是在遇到问题时如何去克服,如何去解决那才是关键所在,要用尽自己所知去想,找资料,问同学,问老师,不懂就问,才有可能去解决问题。

大学,就这样临近尾声了,而我也即将离开这个学校,离开我的同学们,离开我敬爱的老师们,心里难免有一种舍不得的情结,这是正常的,但是换一个角度去看,或许这对我们来说都是必须要经历的,说明我们长大了,总要自己去生活,自己去面对各种各样的难题的一天,而我也会在未来的人生中记住这一段友情,师生情。在这里,再次对在此次设计中给予我援助之手的同学们和老师们,说一声,谢谢,真的很感谢你们。也希望你们在未来生活中越来越好。

程序


#include "config.h"	//用户需要添加的头文件

//对应的引脚定义,需要跟原理图一致
sbit BEEP = P3^7;
sbit LEDGREEN = P3^6;
sbit LEDRED = P3^5;

//宏定义,类似替换的功能
#define LEDON 0	 //led灯亮
#define LEDOFF 1 //led灯灭
#define BEEPON 0 //蜂鸣器响
#define BEEPOFF 1 //蜂鸣器不响

/*——————————————————————————————————————————————————————————————————————————————————*/
xdata uchar KeyABuf[6] = {0xAA,0x55,0xBB,0x66,0xCC,0x77};//注册时写入IC卡的A密钥
xdata uchar Default_KeyABuf[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//注销时写入IC卡的密钥
xdata uchar CardRevBuf[16] = {0}; //读到IC卡时,缓存起来的卡号
xdata uchar CardKeyABlockBuf[16] = {0,0,0,0,0,0,0xff,0x07,0x80,0x69,0,0,0,0,0,0};//操作IC卡A密钥时的指令数组
/*——————————————————————————————————————————————————————————————————————————————————*/

uchar SYS_STATUS,pre_sysstatus = 0XFF;//当前系统状态,上一次系统状态
uchar cardstatuss=0;//卡片的状态
/********************************************************************
* 作者 :比酷wyh
* 名称 : 
* 功能 : 
* 输入 : 
* 输出 : 
***********************************************************************/
void DelayMs(uint i)//1ms延时
{
	uint x,j;
	for(j=0;j<i;j++)
	for(x=0;x<=110;x++);	
}
/********************************************************************
* 作者 :比酷wyh
* 名称 : Change_Card_id
* 功能 : 
* 输入 : 
* 输出 : 
***********************************************************************/
uchar * Change_Card_id( uchar * SrcBuf)//将4字节(32bit)的序列号(卡号)转成对应的字符串
{
	xdata char DisplayBuf[10];
	char *pDisplayChar;
	uchar Tmp, i;

	pDisplayChar = DisplayBuf;

	for( i = 0; i < 4; i++ )
	{
		Tmp = ( ( *SrcBuf ) >> 4 ) & 0x0F;	
		if( ( Tmp >=0 ) && ( Tmp <= 9 )	)
		{
			*pDisplayChar ++ = '0' + Tmp;//将数字转成对应的字符0~9	
		}
		else
		{
			*pDisplayChar ++ = 'A' + Tmp - 10;//将数字转成对应的字符A~F
		}

		Tmp = ( *SrcBuf ) & 0x0F;	
		if( ( Tmp >=0 ) && ( Tmp <= 9 )	)
		{
			*pDisplayChar ++ = '0' + Tmp;//将数字转成对应的字符0~9	
		}
		else
		{
			*pDisplayChar ++ = 'A' + Tmp - 10;//将数字转成对应的字符A~F
		}

		SrcBuf ++;
	}
	*pDisplayChar ++ = '\0';

	return DisplayBuf;	
}
/********************************************************************
* 作者 :比酷wyh
* 名称 : Updata_Card
* 功能 : 
* 输入 : 
* 输出 : 
***********************************************************************/
uchar Updata_Card(uchar res)//对卡片进行注册或者注销	 
{
	xdata uchar CardKeyABufMatch[6]; //要验证的A密钥

	if(res)//对卡片进行注销,将卡片的A密钥写入Default_KeyABuf
	{
		memcpy( CardKeyABlockBuf, Default_KeyABuf, 6);//将6个字节的A密钥复制到CardKeyABlockBuf的前6个字节中
		memcpy( CardKeyABufMatch, KeyABuf, 6 );
	}
	else//对卡片进行注册,将卡片的A密钥写入KeyABuf
	{
		memcpy( CardKeyABlockBuf, KeyABuf, 6);//将6个字节的A密钥复制到CardKeyABlockBuf的前6个字节中
		memcpy( CardKeyABufMatch, Default_KeyABuf, 6 );
	}

	if( PcdRequest( PICC_REQIDL, &CardRevBuf[0] ) != MI_OK )//寻天线区内未进入休眠状态的卡	
	{  
		if( PcdRequest( PICC_REQIDL, &CardRevBuf[0] ) != MI_OK )//寻天线区内未进入休眠状态的卡	
		{  
			return 0;//无卡
		}
	}

	if( PcdAnticoll( &CardRevBuf[2] ) != MI_OK ) //防冲撞 
	{
		return 0;//无卡	
	}
	
	if( PcdSelect( &CardRevBuf[2] ) != MI_OK )//选卡
	{
		return 0;//无卡
	}

	if( PcdAuthState( PICC_AUTHENT1A, KEY_A_ADDR_1, CardKeyABufMatch, &CardRevBuf[2] ) != MI_OK )// 验证密码
	{
		return 0;//验证失败	
	}

	if( PcdWrite( KEY_A_ADDR_1, CardKeyABlockBuf ) != MI_OK )//修改卡片A密钥
	{
		return 0;
	}
	return 1;
}
/********************************************************************
* 作者 :比酷wyh
* 名称 : 
* 功能 : 
* 输入 : 
* 输出 : 
***********************************************************************/
uchar Check_Card( void )//检测周围卡片状态
{
	if( PcdRequest( PICC_REQIDL, &CardRevBuf[0] ) != MI_OK )//寻天线区内未进入休眠状态的卡
	{
		if( PcdRequest( PICC_REQIDL, &CardRevBuf[0] ) != MI_OK )//寻天线区内未进入休眠状态的卡
		{
			return NOCARD;//无卡	
		}	
	}

	if( PcdAnticoll( &CardRevBuf[2] ) != MI_OK ) //防冲撞
	{
		return NOCARD;//无卡	
	}

	if( PcdSelect( &CardRevBuf[2] ) != MI_OK )//选卡
	{
		return NOCARD;//无卡
	}

	if( PcdAuthState( PICC_AUTHENT1A, KEY_A_ADDR_1, KeyABuf, &CardRevBuf[2] ) != MI_OK )//验证卡片A密钥	  
	{
		return NOREG;//未注册的卡片
	}
	else   
	{
		return HAVEREG;//已注册的卡片
	}
}
/********************************************************************
* 作者 :比酷wyh
* 名称 : 
* 功能 : 
* 输入 : 
* 输出 : 
***********************************************************************/
int main(void)
{
	uchar keyvalue;//按键值
	bit bhavereg=0,sendid=0;
	uchar buff[20];

	UART1_Init();//串口1初始化,和PC端通信
	EA=1;//开总中断

	LEDRED = LEDOFF;
	LEDGREEN = LEDOFF;
	BEEP = BEEPON;

	Lcd12864_Init();//液晶LCD12864初始化		
	Lcd12864_ClrScreen();//清除屏幕显示内容

	SYS_STATUS = SHOWTIME; 
		
	Rc522_Init(); //刷卡模块初始化

	DS3231_Init();//DS3231时间模块初始化

	DelayMs(200);
	BEEP = BEEPOFF;

	DelayMs(300);

	UART1_CLR_Buf();//清空串口的缓存数据

	while(1)
	{	
		if(pre_sysstatus != SYS_STATUS) //状态改变一次 液晶清屏一次
		{
			pre_sysstatus = SYS_STATUS;
			Lcd12864_ClrScreen();//清除屏幕显示内容
		}

		switch(SYS_STATUS)
		{			
			case CREATSHUJI://新建书籍界面
			Lcd12864_PutString(0,2,"正在录入");
			Lcd12864_PutString(1,2,"请扫描图书");
			Lcd12864_PutString(3,5,"退出");
			cardstatuss = Check_Card();//获取IC卡的状态
			if(cardstatuss == NOREG || cardstatuss == HAVEREG)//有卡片
			{					
				if(cardstatuss == HAVEREG)
				{
					if(Updata_Card(1)==1)//注销卡片成功
					{
						
					}
				}
				if(sendid==0)//将卡号发送到电脑上位机
				{
					if(Updata_Card(0)==1)//注册卡片成功
					{
						UART1_SendString(Change_Card_id(&CardRevBuf[2]));
						UART1_SendByte('G');
						sendid=1;
						BEEP = BEEPON;
						DelayMs(100);
						BEEP = BEEPOFF;
					}
				}
				if(strstr(Uart1_Buf,"OK1") != NULL)//接受到OK1字符,表示新建用户成功
				{
				   	UART1_SendString(Change_Card_id(&CardRevBuf[2]));
					UART1_SendByte('H');					
					Lcd12864_PutString(2,1,"图书录入成功");
					BEEP = BEEPON;
					DelayMs(100);
					BEEP = BEEPOFF;
					DelayMs(1000);
					Lcd12864_ClrScreen();//清除屏幕显示内容	
					UART1_CLR_Buf();//接受完要清空串口的缓存数据							
				}
				else if(strstr(Uart1_Buf,"Error1") != NULL)//接受到Error字符,该卡片无效
				{
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
					BEEP = BEEPON;
					LEDRED = LEDON;
					Lcd12864_PutString(2,0,"  该书籍已录入  ");
					DelayMs(1000);
					BEEP = BEEPOFF;	
					Lcd12864_PutString(2,0,"                ");
					LEDRED = LEDOFF;
				}															
			}
			else 
			{
				sendid=0;//拿开卡片后,等待下次卡片到来
			}
			keyvalue = ScanKeyValue();//扫描按键
			if(keyvalue == VALUE_KEY_2)//按键2	
			{	 
				SYS_STATUS = SHOWTIME;//返回		
			}
			break;

			case JIESHU://借书界面
			Lcd12864_PutString(0,2,"正在借书");
			Lcd12864_PutString(1,2,"请扫描图书");
			Lcd12864_PutString(3,5,"退出");
			cardstatuss = Check_Card();//获取IC卡的状态
			if(cardstatuss == HAVEREG)//已注册的卡片
			{					
				if(sendid==0)//将卡号发送到电脑上位机
				{
					UART1_SendString(Change_Card_id(&CardRevBuf[2]));
					UART1_SendByte('I');
					sendid=1;
				}
				if(strstr(Uart1_Buf,"OK2") != NULL)//接受到OK2字符,表示该卡片有效
				{
					DelayMs(300);//等待数据全部接收完成
					Lcd12864_ClrScreen();//清除屏幕显示内容
					//开始显示图书信息					
					memcpy(&buff[20-16],&Uart1_Buf[3],16);//书名最长8个字=16个字符
					Lcd12864_PutString(0,0,&buff[20-16]);	

					memcpy(&buff[20-8],&Uart1_Buf[3+16],8);//作者名字最长4个字
					Lcd12864_PutString(1,0,&buff[20-8]);
											
					memcpy(&buff[20-16],&Uart1_Buf[3+16+8],16);//出版社最长8个字=16个字符
					Lcd12864_PutString(2,0,&buff[20-16]);	

					Lcd12864_PutString(3,2,"借书成功");

					LEDGREEN = LEDON;
					BEEP = BEEPON;
					DelayMs(100);
					BEEP = BEEPOFF;
					DelayMs(100);
					BEEP = BEEPON;
					DelayMs(100);
					BEEP = BEEPOFF;
					LEDGREEN = LEDOFF;
					DelayMs(4000);	
					Lcd12864_ClrScreen();//清除屏幕显示内容							
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
				}
				else if(strstr(Uart1_Buf,"Error2") != NULL)//接受到Error2字符,表示该卡片无效
				{
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
					BEEP = BEEPON;
					LEDRED = LEDON;
					Lcd12864_PutString(2,0,"  该书籍不存在  ");
					DelayMs(1000);
					BEEP = BEEPOFF;	
					Lcd12864_PutString(2,0,"                ");
					LEDRED = LEDOFF;
				}	
				else if(strstr(Uart1_Buf,"Error3") != NULL)//接受到Error3字符,表示该卡片已借
				{
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
					BEEP = BEEPON;
					LEDRED = LEDON;
					Lcd12864_PutString(2,0,"  该书籍已借出  ");
					DelayMs(1000);
					BEEP = BEEPOFF;	
					Lcd12864_PutString(2,0,"                ");
					LEDRED = LEDOFF;
				}															
			}
			else if(cardstatuss == NOREG)//未注册的卡片
			{
				BEEP = BEEPON;
				LEDRED = LEDON;
				Lcd12864_PutString(2,0,"  该书籍不存在  ");
				DelayMs(1000);
				BEEP = BEEPOFF;	
				Lcd12864_PutString(2,0,"                ");
				LEDRED = LEDOFF;
			} 
			else 
			{
				sendid=0;//拿开卡片后,等待下次卡片到来
			}
			keyvalue = ScanKeyValue();//扫描按键
			if(keyvalue == VALUE_KEY_2)//按键2	
			{	 
				SYS_STATUS = SHOWTIME;//返回		
			}
			break;
			
			case HUANSHU://还书界面
			Lcd12864_PutString(0,2,"正在还书");
			Lcd12864_PutString(1,2,"请扫描图书");
			Lcd12864_PutString(3,5,"退出");
			cardstatuss = Check_Card();//获取IC卡的状态
			if(cardstatuss == HAVEREG)//已注册的卡片
			{					
				if(sendid==0)//将卡号发送到电脑上位机
				{
					UART1_SendString(Change_Card_id(&CardRevBuf[2]));
					UART1_SendByte('J');
					sendid=1;
				}
				if(strstr(Uart1_Buf,"OK3") != NULL)//接受到OK2字符,表示该卡片有效
				{
					DelayMs(300);//等待数据全部接收完成
					Lcd12864_ClrScreen();//清除屏幕显示内容
					//开始显示图书信息					
					memcpy(&buff[20-16],&Uart1_Buf[3],16);//书名最长8个字=16个字符
					Lcd12864_PutString(0,0,&buff[20-16]);	

					memcpy(&buff[20-8],&Uart1_Buf[3+16],8);//作者名字最长4个字
					Lcd12864_PutString(1,0,&buff[20-8]);
											
					memcpy(&buff[20-16],&Uart1_Buf[3+16+8],16);//出版社最长8个字=16个字符
					Lcd12864_PutString(2,0,&buff[20-16]);	

					Lcd12864_PutString(3,2,"还书成功");

					LEDGREEN = LEDON;
					BEEP = BEEPON;
					DelayMs(100);
					BEEP = BEEPOFF;
					DelayMs(100);
					BEEP = BEEPON;
					DelayMs(100);
					BEEP = BEEPOFF;
					LEDGREEN = LEDOFF;
					DelayMs(4000);	
					Lcd12864_ClrScreen();//清除屏幕显示内容							
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
				}
				else if(strstr(Uart1_Buf,"Error5") != NULL)//接受到Error5字符,表示该卡片无效
				{
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
					BEEP = BEEPON;
					LEDRED = LEDON;
					Lcd12864_PutString(2,0,"  该书籍不存在  ");
					DelayMs(1000);
					BEEP = BEEPOFF;	
					Lcd12864_PutString(2,0,"                ");
					LEDRED = LEDOFF;
				}	
				else if(strstr(Uart1_Buf,"Error4") != NULL)//接受到Error3字符,表示该卡片已还
				{
					UART1_CLR_Buf();//接受完要清空串口的缓存数据
					BEEP = BEEPON;
					LEDRED = LEDON;
					Lcd12864_PutString(2,0,"  该书籍已归还  ");
					DelayMs(1000);
					BEEP = BEEPOFF;	
					Lcd12864_PutString(2,0,"                ");
					LEDRED = LEDOFF;
				}															
			}
			else if(cardstatuss == NOREG)//未注册的卡片
			{
				BEEP = BEEPON;
				LEDRED = LEDON;
				Lcd12864_PutString(2,0,"  该书籍不存在  ");
				DelayMs(1000);
				BEEP = BEEPOFF;	
				Lcd12864_PutString(2,0,"                ");
				LEDRED = LEDOFF;
			} 
			else 
			{
				sendid=0;//拿开卡片后,等待下次卡片到来
			}
			keyvalue = ScanKeyValue();//扫描按键
			if(keyvalue == VALUE_KEY_2)//按键2	
			{	 
				SYS_STATUS = SHOWTIME;//返回		
			}
			break;
							
			case SHOWTIME://显示时间			
			DS3231_Readtime();//读取时间
			Lcd12864_PutString(0,0,"  ");
			Lcd12864_PutData(Year/10+'0');
			Lcd12864_PutData(Year%10+'0');
			Lcd12864_PutString(0,2,"年");
			Lcd12864_PutData(Month/10+'0');
			Lcd12864_PutData(Month%10+'0');
			Lcd12864_PutString(0,4,"月");
			Lcd12864_PutData(Date/10+'0');
			Lcd12864_PutData(Date%10+'0');
			Lcd12864_PutString(0,6,"号");
			Lcd12864_PutString(1,1,"");
			Lcd12864_PutData(Hour/10+'0');
			Lcd12864_PutData(Hour%10+'0');
			Lcd12864_PutString(1,2,"时");
			Lcd12864_PutData(Min/10+'0');
			Lcd12864_PutData(Min%10+'0');
			Lcd12864_PutString(1,4,"分");
			Lcd12864_PutData(Sec/10+'0');
			Lcd12864_PutData(Sec%10+'0');
			Lcd12864_PutString(1,6,"秒");
			Lcd12864_PutString(2,2,"星期");
			switch(Day)
			{
				case 0x01:
				Lcd12864_PutString(2,4,"日");
				break;
				case 0x02:
				Lcd12864_PutString(2,4,"一");
				break;
				case 0x03:
				Lcd12864_PutString(2,4,"二");
				break;
				case 0x04:
				Lcd12864_PutString(2,4,"三");
				break;
				case 0x05:
				Lcd12864_PutString(2,4,"四");
				break;
				case 0x06:
				Lcd12864_PutString(2,4,"五");
				break;
				case 0x07:
				Lcd12864_PutString(2,4,"六");
				break;
			}
			Lcd12864_PutString(3,0,"  借书    还书  ");
			keyvalue = ScanKeyValue();//扫描按键
			if(keyvalue == VALUE_KEY_1)//按键1	
			{	 
				SYS_STATUS = JIESHU;//进入借书 	
				UART1_CLR_Buf();//接受完要清空串口的缓存数据	
			}
			else if(keyvalue == VALUE_KEY_2)//按键2	
			{	 
				SYS_STATUS = HUANSHU;//进入还书 
				UART1_CLR_Buf();//接受完要清空串口的缓存数据		
			}	
			if(strstr(Uart1_Buf,"Se") != NULL) //接受到Se字符,同步时间,201903101746327Se
			{
				Year = (Uart1_Buf[2]-0x30)*10+(Uart1_Buf[3]-0x30);
				Month = (Uart1_Buf[4]-0x30)*10+(Uart1_Buf[5]-0x30);
				Date = (Uart1_Buf[6]-0x30)*10+(Uart1_Buf[7]-0x30);
				Hour = (Uart1_Buf[8]-0x30)*10+(Uart1_Buf[9]-0x30);
				Min = (Uart1_Buf[10]-0x30)*10+(Uart1_Buf[11]-0x30);
				Sec = (Uart1_Buf[12]-0x30)*10+(Uart1_Buf[13]-0x30);
				Day = (Uart1_Buf[14]-0x30);
				DS3231_ModifyTime(Year,Month,Date,Hour,Min,Sec,Day);
				UART1_CLR_Buf();//接受完要清空串口的缓存数据
			}	
			if(strstr(Uart1_Buf,"Creat") != NULL)//接受到Creat字符,新建书籍,注册卡片,
			{				
				SYS_STATUS = CREATSHUJI;//进入界面
				UART1_CLR_Buf();//接受完要清空串口的缓存数据
			}									
			break;						
		}	
	}
	return 1;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值