基于单片机的RFID门禁系统设计与实现

目 录

摘 要 I
Abstract II
引 言 1
1 控制系统设计 3
1.1 主控制器选择 3
1.2 项目总体设计 3
2 项目硬件设计 5
2.1 单片机控制模块 5
2.2 射频识别模块 8
2.3 矩阵键盘模块 9
2.4 液晶显示模块 10
2.5 报警模块 11
2.6 AT24C02存储模块 12
2.7 继电器驱动模块 13
2.8 总电路图设计 13
3 项目软件设计 14
3.1 软件开发环境及流程 14
3.2 系统主程序设计 15
3.3 LCD显示程序设计 16
3.4 按键程序设计 18
4 项目调试 21
4.1 电路焊接 21
4.2 系统程序调试 22
4.3 实物调试 23
结 论 24
参考文献 25
附录1 总电路原理图 27
附录2 源程序代码 28
致 谢 53

摘 要

门禁系统是一种面向人们生活的社区,家庭,旅馆等地方,并且可以通过一个锁一张卡进行独立管理,或者一个锁多张卡进行集中管理的系统。本文设计了一种使用方便,安全性高的基于单片机的RFID门禁系统。
本设计主要利用STC89C52单片机对系统进行控制,由最小系统、射频识别模块、液晶显示模块等组成的硬件系统,以及通过C语言开发程序进行代码的设计和编写的软件系统,最终实现射频识别功能以及密码识别功能。本设计的目标是使设计出来的系统能提高安全指数,刷卡识别准确,给生活带来方便,被更多人所应用。
结果表明本设计很好地实现了射频识别功能以及密码识别功能,预期功能全部实现。使用单片机进行控制保证了系统的稳定性,RFID技术的应用使得门禁系统的管理和使用更加方便和安全。RFID技术已经被应用在了便携式和小型轻量化方向上的许多电子产品中,且已经开发出了许多的非接触式RFID卡控制系统。目前,非接触式RFID卡已经在公交卡、金融卡、门禁卡、校园一卡通等许多领域得到了广泛的应用。这使人们在实际生活中不需要为环境是否安全而困扰,也让许多管理更加详细,高效和准确。

关键词:RFID; 门禁系统; 液晶显示; 单片机控制

Abstract

The access control system is a system that faces people’s lives in communities, families, hotels and other places, and can be independently managed by one lock one card, or a centralized management by locking multiple cards. This paper designs a RFID access control system based on single chip microcomputer which is easy to use and has high security.
This design mainly uses STC89C52 single-chip microcomputer to control the system, a hardware system composed of a minimum system, a radio frequency identification module, a liquid crystal display module, etc., and a software system to carefully design and write code through the C language development program. Finally realize the radio frequency identification function and password identification function. The goal of this design is to enable the designed system to improve the safety index, identify the card swiping accurately, bring convenience to life, and be used by more people.
The results show that the design has realized the radio frequency identification function and the password identification function well, and the expected functions are all realized. The use of single chip microcomputer for control ensures the stability of the system. The application of RFID technology makes the management and use of the access control system more convenient and safe. RFID technology has been applied to many electronic products in the direction of portable and small and light weight, and many non-contact RFID card control systems have been developed. At present, non-contact RFID cards have been widely used in many fields such as bus cards, financial cards, access control cards, and campus cards. This eliminates the need for people to worry about the safety of the environment in real life, and also makes many management more detailed, efficient and accurate.

Keywords: RFID; access control system; liquid crystal display; Single-Chip Microcomputer control

引 言

随着当代社会的不断进步和科技的飞速发展,急需一种现代化的智能门禁系统来满足人们对安全的需求,因为常见的普通的门锁安全系数低,且使用不方便。这时就需要一种面向现代建筑的自动化的系统,智能门禁系统因此而研发。目前生活中已经出现了多种多样的智能门禁系统,这些门禁系统各自有各自的优点和性能,目前随着门禁系统新功能的不断改进,门禁系统的热度越来越高[5]。本设计提出了基于单片机的RFID门禁系统的设计,对其中一个核心的组成部分“门禁控制系统”的硬件与软件方面进行了仔细的分析与设计。这一门禁系统是确保居民及其财产安全的一项重要解决方法。研究这一门禁系统意义深远,对于我们的日常生活有很大的帮助。
射频识别(RFID)技术是非接触式的,即RFID超高频读卡器可以在指定范围内读取标签,而无需触摸标签。射频识别系统主要由RFID信号发射部分、RFID信号接收部分和RFID发射接收天线组成[11]。在本设计中,通过RFID技术,可以实现RFID卡的注册和注销,然后根据接收到的RFID卡信息,判断是否为已注册卡,最终来控制门的开关,RFID技术应用在本设计中,有许多优点,比如读写速度快,可以节省使用者的时间,十分便利;可同时使用多张RFID卡,一机多卡,可以多人共同使用,满足了一些家庭或工作场所的需求;使用安全性高,不容易发生识别错误,导致出现误开关门的情况,而且可以很好的防止一些盗窃行为的发生;这些优点使得RFID技术被越来越多的应用,使人们因为经济水平的高速发展而对建筑内部安全性的担心问题得到了解决。
欧美的门禁系统目前发展的很快,超过了很多国家的技术,好多公司都已经做到了产业分工明确,研发技术先进。科技在发展,门禁系统的研究也同样越来越被重视,磁卡和接触式门禁系统会随着科技的发展,而被具备更多功能的门禁系统取代,取而代之的是具有良好性能的非接触式门禁系统。RFID技术在国外许多国家已经发展的十分成熟和先进[15]。目前国内门禁系统的研究已经由开始的认识研究阶段发展到了自主研究阶段,个别本土商已经研发出了指纹识别芯片。门禁系统有一个核心就是控制器,但是这个核心控制器许多都是由国外的公司研制与开发出来的。由于目前我国电子技术的不断提高,门禁系统的功能也在不断增加。但是相比于国外的先进技术,我国在RFID芯片技术方面仍存在差距[18]。
智能门禁系统可以对生活中一些建筑里重要的通道进行管理。如果有人想要进入,必须要使用已注册的RFID卡,或者是输入正确的密码,才可以通过,这种门禁系统大大的提升了安全性。传统的机械锁即使是使用了非常结实的原材料,但是总是能被各种各样的方法打开,而且如果遇到钥匙丢失的问题,还需要找专业的人员来开锁,进行换锁、换钥匙等操作,十分麻烦。而门禁系统结合了许多种高科技的技术,通过RFID卡就能控制门的状态,使用方便,安全性高,能够让使用者的安全和财产得到保护。
随着科技的发展,生活中盗窃与抢劫时有发生,而且犯罪手段越来越高明,为了阻止这些犯罪行为,人们的安全防范意识必须要提高,被人们所熟知的传统的门锁和防盗门已经无法满足需求了。而门禁系统的研发则解决了很大的问题,越来越多的人开始把它应用到生活中。所以如果设计一种使用安全的门禁系统,可以很好地解决这些问题。
基于这种对门禁系统的需求,本设计提出了一种基于单片机的RFID门禁系统,本设计主要通过STC89C52单片机进行控制,LCD12864液晶显示屏显示关于门禁系统的信息[19],利用AT24C02存储芯片来存储卡序列号,通过密码识别和射频识别控制开关门锁,同时可以修改密码、注册和注销RFID卡。本设计安全实用,使用方法简单方便。本篇文章共分为四个章节,具体的介绍了这种基于单片机的RFID门禁系统:
第一章介绍了主控制器的选择,以及项目的总体设计分成的几个模块,做出了系统的结构框图。
第二章介绍了门禁系统的硬件组成方面,包括部分硬件型号的选择;各个模块工作原理以及电路原理图。
第三章介绍了系统程序通过软件的运行,讲述了系统的开发环境和主程序流程图以及各个子程序流程图。
第四章介绍了系统的各个部分调试,分别为电路焊接、程序调试以及实物调试。

1 控制系统设计

1.1 主控制器选择
RFID门禁系统设计可以通过一个主控制器来实现,通过查找资料和学习,提出了两种可供选择的主控制器,分别为单片机控制和DSP控制,具体方案如下:
方案一:主控制器选用单片机。单片机是一种虽然小但很完整的芯片,应用在集成电路中[2]。芯片中包含随机储存器RAM、中央处理器CPU、只读存储器ROM、中断、定时器以及I/O口等模块[6],个别还可以把模拟信号转换成数字信号或者把数字信号转换成模拟信号。总的来说,可以对一个字节8位里的每一位进行单独处理、强调控制和事务处理功能、市面价格便宜、开发环境完备且成熟、开发工具齐全,应用资料应有尽有等,都是单片机的特点。
方案二:主控制器选用DSP。DSP可以按照某种电路的运行流程,编写程序,然后再输入到芯片内,一个数字信号处理器把所有单元集合在一块很小的芯片中[13],在DSP的外侧可以连接许多存储器,功能比较全,可以进行通信,就像是一个小型的计算机。
与单片机相比,DSP需要较高的计算能力和相对复杂的控制算法。而单片机应用广泛,控制算法相对简单,经济实惠,成本相对较低,同时也可以满足本设计的需要。综合以上,本设计的主控制器最终选用单片机。
1.2 项目总体设计
本项目基于单片机的RFID门禁系统设计由:STC89C52单片机、矩阵键盘、12864液晶显示、报警、继电器驱动模块、RFID-RC522射频识别模块、AT24C02存储模块组成。通过密码识别和射频识别控制门锁,构成完整的门禁系统。由如下模块组成:
(1)最小系统模块:STC89C52单片机作为系统的主控制器,接收密码识别模块和射频识别模块的信息[21],经过处理再传递到液晶显示模块和继电器驱动模块;
(2)液晶显示模块:LCD12864液晶显示屏,接收密码识别模块和射频识别模块的信息,显示密码或RFID卡是否正确,是否可以通过;
(3)密码识别模块:由存储器、解调器、键盘等组成,通过对键盘输入密码信息进行分析识别,最终传递到液晶显示模块,实现密码识别功能[1];
(4)射频识别模块:首先通过MFRC522读卡器读取用户的RFID卡信息,然后读取的信息用来识别RFID卡是否为已注册卡,最终传递到液晶显示模块,实现RFID卡识别功能[17];
(5)AT24C02存储模块:读卡器读取到RFID卡信息之后,信息会存储在AT24C02中,这时单片机再接收到新的数据,就可以和AT24C02中的信息作比较,看信息是否相同,从而决定开关门[12]。
(6)继电器驱动模块:接收到的新的信息与AT24C02中存储的信息进行比较之后,结合蜂鸣器和指示灯[4],控制电磁锁的吸合,进而控制门的状态。
本系统结构框图如图1.1所示。

图1.1 系统结构框图
电源供电后,单片机通过对RFID卡信息和按键输入信息进行处理,经转换后传输给步进电机驱动电路、液晶显示电路、报警电路,完成系统的运行。

2 项目硬件设计

2.1 单片机控制模块
2.1.1 单片机型号选择
基于单片机的RFID门禁系统设计,对单片机存储空间的要求是有拥有4K字节EEPROM。其次为了保证系统更好地运行,要选用稳定性高的控制器,还要考虑到价格、编程下载难易程度等方面。基于此有以下两种方案可供选择。
方案一:主控制器选用STC89C52单片机[16]。该单片机可以满足对单片机存储空间的要求拥有4K字节EEPROM。具有低功耗、高性能、可直接使用串口下载的特点。STC89C52单片机具有开发简单[3],可在线编程下载,成本相对较低的优点。
方案二:主控制器选用AT89S52单片机[7]。AT89S52单片机的内部存储器密度高,而且在断电之后,其内部存储的信息会保存起来。该单片机自带2KB的EEPROM存储空间、8K字节程序存储空间[8]。适用于常规编程器。但是AT89S52的价格相对来说比较高,开发方法相对复杂,难度较高。
综上,与AT89S52单片机相比,STC89C52单片机开发难度较低、稳定性高,而且价格在可以接受的范围内,结合本设计预期实现的功能对产品性能的要求,最终决定使用STC89C52单片机作为主控制器。
2.1.2 单片机的引脚说明
STC89C52单片机共有32位I/O口线,引脚图如图2.1所示。本设计刚好需要32个,其中11个I/O口与LCD12864液晶显示模块相连接,使其能显示信息;1个I/O口与蜂鸣器报警模块相连接,使其发出声音;8个I/O口与按键模块相连接,使按键可以使用;RFID模块需要5个,AT24C02存储模块需要1个,复位电路需要1个,时钟电路需要2个,继电器驱动模块需要1个,下载口需要2个。STC89C52单片机的工作电压为5V。

图2.1 STC89C52单片机引脚图
单片机的下载接口如图2.2所示,单片机的P30与P31管脚作用是下载相关的程序[8],与下载接口相连,用来下载程序。

图2.2 下载接口原理图
具体引脚对应功能如表2.3所示。
表2.3 STC89C52单片机引脚功能表

引脚名称 功能
P1.0~P1.7 8位双向I/O口
RST 复位端
RXD 串行口输入端
TXD 串行口l输出端
INT0/INT1 外部中断0/1输入
T0/T1 定时器0/1输入
XTAL2/XTAL1 接晶振
VCC/VSS 电源
P3.0~P3.7 8位双向I/O口
WR/RD 片外数据存储
2.1.3 单片机最小系统
单片机最小系统是指用最少的元件组成的单片机可以工作的系统。单片机最小系统原理图如图2.4所示。对52系列单片机来说,最小系统一般应该包括:电源电路、时钟电路、复位电路[9];功能是对数据进行接收、转换和传输。选用5V电源作为系统的总电源,为单片机最小系统供电。在电源线插入电源接口之后,按下SW1,VCC接通电源线,整个系统通电运行。

图2.4 单片机最小系统原理图
复位电路:当复位后单片机就会从头开始执行程序,如果在单片机的执行程序过程中,触发了复位,则单片机会被强行重新开始执行程序。
本设计的复位有按键手动复位和上电复位两种方式。VCC首先经过一个10μF的电解电容,一方面接到单片机第9脚,另一方面经过一个10KΩ的限流电阻接地,电容的作用是隔绝直流电,通过交流电,VCC给电解电容充电的时间大于两个记忆周期,完成一次复位。按下按键K1,也可以完成一次复位。复位电路如图2.5所示。

图2.5 复位电路原理图
时钟电路:单片机处理任何事件都需要时序,时钟晶振电路为系统稳定运行提供保障。时钟电路原理图如图2.6所示,时钟电路主要是由两个部分构成,一个晶振以及两个电容使数字控制器上电以后可以正常工作。在图2.6中,起到稳定频率和快速起振作用的是电容C6和C7[14],电容值在5~30pF,典型值为30pF[20]。晶振CY1的两个管脚分别接单片机的第18、19脚。

图2.6 时钟电路原理图
2.2 射频识别模块
本设计的射频识别模块采用MFRC522非接触读卡器芯片实现读写卡功能[22]。读卡器的微控制单元选取的是TI单片机MSP430F149,该单片机功率损耗低,模式多种多样,反应速度也很快;它有60KB的闪存,2KB的RAM。
由于STC89C52的SPI接口数量有限,所以MFRC522的接口模式选择通过软件模拟SPI模式。
射频识别模块采用SPI总线通信,共有8个管脚,VCC和GND占用了两个管脚,RST为复位,SDA为数据输出,SCK为同步时钟,MOSI为主输出从输入,MISO为主输入从输出[9]。因为这几个管脚与单片机相连时工作电压是3.3V,而单片机的工作电压为5V,所以要分别串联一个330Ω的电阻进行分压。
射频识别模块如图2.7所示。

图2.7 射频识别模块原理图
因为RFID模块为3.3V电压供电,所以需要设计一个5V转3.3V的电路,如图2.8所示。Vin端接5V电源,GND端接地,Vout输出3.3V电压。

图2.8 转换电路
2.3 矩阵键盘模块
4×4矩阵键盘的作用是完成系统的输入密码与进入选项进行设置等。矩阵键盘电路如图2.9所示。因为如果选用独立式的按键,每一个键均需要使用一根I/O口线,当按键设置为4×4时[9],一共有16个按键,就需要16个I/O口,造成端口浪费的同时使得系统的电路结构趋于复杂,不利于整体的系统设计和具体实现。本设计使用4×4矩阵式键盘相对于独立式键盘来说,避免了按键的重复使用,明确了每个按键的作用,提高了I/O口的利用率,非常适用于本设计的使用。
P13、P12、P11、P10接横向,P14、P15、P16、P17接纵向,这样一个矩阵键盘就连接成功可以正常工作了。

图2.9 矩阵键盘电路原理图
2.4 液晶显示模块
2.4.1 液晶显示模块选择
根据本设计的要求,所选用的显示器要求有多种接口方式,程序编写和调试成功以后,需要在显示界面显示出想要表达的信息和内容。编写显示的程序之后,可以在显示屏上显示出特定的汉字或者图形。同时对工作电压和工作功率也是有要求的,要低于其它的显示器。最重要的一点是,显示器工作的电路设计和软件程序的编程设计要相对容易理解和操作一些。
方案1:使用LCD12864输出显示信息。LCD12864本质上是根据特定的规则排列起来的列阵组成的液晶显示器,分辨率为128×64,该点阵显示成本较低,LCD12864功率的损耗低,体积小,面积小,重量轻,可以显示的信息量大,显示领域广。
方案2:使用LCD1602输出显示信息。LCD1602可以把需要显示的信息输出呈现出来,这些呈现的信息可以供给实时的数据或结果,以便于获得系统的状况信息。但是其显示字体有大小限制,不能显示图形和曲线。
综上,相对于LCD1602来说,LCD12864功率的损耗低,功能多,显示信息量大,结合设计的需求,LCD12864最适合用来输出显示信息。
2.4.2 LCD12864模块设计
LCD12864为本设计的显示部分,12864表示该模块在水平方向和竖直方向上分别显示128和64个点[3],该显示屏用来显示密码正确与否,RFID卡是否为已注册卡,进入设置功能等。LCD12864的一个优点是接口种类比较繁多,加以相关的程序代码,就可以在这块显示屏上描述出用户想要表达的汉字和图形信息。
LCD12864是一个液晶显示屏,它带有20个管脚,有8个管脚是数据管脚,分别是DB0-DB7,DB0-DB7接单片机P0管脚;RS、RW、EN接单片机25、26、27管脚;V0用来调节对比度;液晶显示有两组VCC和GND,因为背景光的电源和液晶的电源是分开的,BLA和BLK是背景光的电源;PSB用来选择并口还是串口。其原理图如图2.10所示。

图2.10 液晶显示模块原理图
2.5 报警模块
2.5.1 蜂鸣器选择
本设计要求,系统统计连续输入错误密码的次数,如果超过三次,蜂鸣器就会发出持续的蜂鸣声,为了实现这一功能,需要选取一种程序控制方便的蜂鸣器。
方案一:有源蜂鸣器。有源蜂鸣器是一种将软件、硬件与通信技术组合在一起的电子蜂鸣器。它是一个有自己的振荡电路的蜂鸣器,只需要通过电平驱动发出鸣响。
方案二:无源蜂鸣器。无源蜂鸣器没有自己的震荡电路,所以不能通过直流信号发声,要想使其发声,需要用一个2K-5K方波来驱动[12]。相对于有源蜂鸣器的使用来说,要比较复杂。
综上,相比于无源蜂鸣器,对有源蜂鸣器进行控制和管理更加简洁方便,功能更多,所以最终选用带有震荡源的5V有源蜂鸣器来实现设计的报警功能。
2.5.2 报警模块设计
报警模块在输入错误密码连续累计达到三次时开始工作,工作原理为,蜂鸣器的A端接VCC,B端接一个PNP型的三极管,PNP三极管基极电平为低电平,三极管会导通,导通之后的三极管可以看成一条线[5],这时蜂鸣器的两端相当于分别接VCC和GND,蜂鸣器开始工作,发出连续的蜂鸣。
报警模块如图2.11所示。

图2.11 报警模块原理图
2.6 AT24C02存储模块
本设计采用AT24C02存储芯片作为存储设备,用来存储从读卡器读取来的RFID卡序列号。
AT24C02存储芯片一共有8个引脚,1、2、3、4管脚接地;表示只有一个AT24C02器件被总线寻找操作数或操作数所在地址,即被总线寻址; AT24C02的5管脚为串行数据输入输出,6管脚为串行时钟输入,这两个管脚与单片机连接,完成通信,在5、6管脚接上拉电阻,用以提高抗干扰能力;第7脚接地,意思是器件可以进行正常的一些操作,如读写操作;第8脚接电源VCC。
AT24C02存储模块原理图如图2.12所示。

图2.12 AT24C02原理图
AT24C02存储模块具体引脚对应功能如表2.13所示。
表2.13 AT24C02引脚功能表

引脚名称 功能
A0-A2 器件地址输入
SDA 串行数据输入输出
SCL 串行时钟输入
WP 写保护
VCC 电源
GND 地
2.7 继电器驱动模块
继电器驱动模块的作用是完成模拟开锁动作。继电器驱动模块原理图如图2.14所示。
继电器共有5个引脚,一个公共点,一个常开点,一个常闭点,剩下的两个角是线圈。R13为限流电阻,IN4007并联到线圈两端来提高负载能力。当P30为高电平时,三极管不导通,电路不工作,为关门状态,开锁指示灯D3不亮;当P30为低电平时,三极管导通,线圈的两脚分别接VCC和地,线圈导电,电路工作,继电器工作,开锁指示灯D3亮起,为开门状态。此时单片机的吸入电流同样也是很小的。三极管放大电流经过继电器。

图2.14 继电器驱动模块原理图
2.8 总电路图设计
本设计采用STC89C52单片机作为主控制器,包括LCD12864液晶显示电路、射频识别电路、报警电路、按键电路、继电器驱动电路以及电源电路[4]。本系统总电路原理图如附录1所示。

3 项目软件设计

3.1 软件开发环境及流程
本设计选用Keil μVision4软件作为单片机的开发环境,该软件开发环境稳定,界面完整,而且支持C语言开发,该软件的运行显示界面如图3.1所示。

图3.1 软件开发界面图
开发时,第一步要在软件中创立一个新的工程文件,点击“New Vision Project”[6],然后给刚刚创建的工程起一个名字,接下来点击保存,下一步因为本设计选用的是STC89C52单片机,所以点击本设计的单片机型号“STC89C52”;这样就成功建立了一个工程,选择“Source Group”按键,可添加.c文件,如果想编辑文件,可以点击“Add”。Keil μVision4软件开发流程如图3.2所示。

图3.2 Keil μVision4软件开发流程图
3.2 系统主程序设计
基于单片机的RFID门禁系统以单片机为主控制器,MFRC522非接触式读卡芯片用来完成本设计的读写RFID卡功能[9],当刷卡时,对卡内信息进行读写,当密码错误超出3次就把键盘锁死报警。门禁系统设计的程序可以实现以下的功能:
(1)可以注册和注销卡;
(2)已注册卡可以开门,没有注册卡则无法开门;
(3)可以设置密码,当使用者遇到忘记携带RFID卡的情况时,可通过键盘手动输入密码,减少了不必要的麻烦;
(4)通过输入原始密码,进入设置页面,就可以对原有的密码进行修改;
(5)如果系统检测到有用户连续3次输入了不正确的密码,则蜂鸣器会发出警报,而且键盘只有通过复位才能恢复正常使用;
(6)信息被12864液晶显示屏接收后,在显示屏上会显示密码的正确与否,RFID卡是不是已注册卡以及设置页面密码的修改、RFID卡的注册与注销。
系统主程序流程图如图3.3所示。

图3.3 系统程序总体流程图
3.3 LCD显示程序设计
3.3.1 LCD初始化
在LCD显示程序设计中,LCD12864的操作可以采取并行的8位接口方式。LCD初始化的运行流程:首先开始程序,延时,设置LCD的工作方式,延时,复位,延时,进行功能设置,延时,进行光标设置,延时,LCD显示屏开始工作,延时,清屏,延时,最后程序结束。
LCD初始化流程图如图3.4所示。

图3.4 LCD初始化流程图
3.3.2 LCD显示
此部分通过LCD显示程序判断出LCD当前是否处于可以接收数据的状态。首先开始程序,LCD进行初始化,延时,判断LCD显示模块的状态,当BF=0时,可以进入写入指令模式,写入指令之后,LCD显示数据,最后结束程序,完成一次LCD显示。
LCD显示流程图如图3.5所示。

图3.5 LCD显示流程图
3.4 按键程序设计
3.4.1 密码验证
通过密码识别来控制开关门,当输入密码时,系统判断是否检测到数据,验证输入的密码是否正确,如果正确则显示屏显示密码正确,电磁锁断开,为开门状态,如果密码错误,则显示屏显示密码错误,电磁锁吸合,门保持关闭状态。密码验证流程图如图3.6所示。

图3.6 密码验证流程图
3.4.2 RFID卡验证
通过RFID卡来控制门的状态,刷卡,系统判断是否检测到数据,如果为已注册卡,则电磁锁断开,为开门状态,如果检测为未注册卡,则电磁锁仍吸合,为关门状态。RFID卡验证的流程图如图3.7所示。

图3.7 RFID卡验证流程图

4 项目调试

4.1 电路焊接
(1)清理焊接点:清除电路板上的锈迹,除去附着在表面上的附着物,例如不必要的焊锡,并露出铜箔的颜色。清理掉电源线的外壳,用刀片轻轻刮蹭,直到露出铜色。
(2)电烙铁通电,等到电烙铁达到一个合适的温度,大概是260度左右时,将电烙铁接触焊锡,并在焊料熔化时立即进行焊接。此时,在电路板铜箔表面上的焊锡应该是半球形。
(3)将导线与焊锡一起放置,并迅速将烙铁放置在导线旁边,焊锡熔化附着在导线上,形成类似于火柴头的形状。
(4)这时导线和电路板铜箔上面均带有焊锡,把他们两个放在一起,利用电烙铁的温度,导线和电路板铜箔会连接在一起,这步焊接就完成了。
(5)注意事项:焊锡粗细不一,我们可以根据焊点的大小来选择。另外,电烙铁的温度也要保持不是特别高,不然松香挥发的快,温度过低也不可以,这样会导致焊接的不够牢固。
在焊接的过程中,将电路板对着原理图进行检查,发现出现了元件方向弄错的问题。解决方法是,对照电路图,确定好该元件的方向,使用吸锡器进行吸锡,把焊错的元件拆下来,重新焊接。
焊接完成后,发现LED指示灯不亮,使用万用表检测是否存在短路与断路等情况,在需要检测的元件或导线的两端分别用两支表笔连通,发现当检测到有些地方时表笔不响,说明电路有问题,接下来对有问题的地方重新焊接。
由于本设计的布线比较复杂,在焊接之前要细心地研究电路图,防止焊接位置错误。如果在焊接时焊锡不够用,加焊锡时要格外小心,因为如果加太多的话,用电烙铁继续焊接时就容易因为焊锡过多而不小心牵连到其它器件。如果遇到焊锡过多的问题,可以用电烙铁放在焊接处来回滑动,这样电烙铁就会将多余的焊锡带走,去除焊锡的另外一个方法是吸锡器,使用十分方便。焊接完毕后的实物图如图4.1所示。

图4.1 焊接实物图
4.2 系统程序调试
(1)首先在Keil μVision4软件中创建一个新的工程:单击菜单栏中的“工程”并为新工程命名,命名后进行保存;选择单片机型号为“STC89C52”;
(2)代码编写与保存:然后在新建的文本中编写本设计的源代码,编写完成之后,对文件进行保存,注意命名为“.c”文件[11],这样就完成了本设计代码的编写。在新建的空白文本中编写程序源代码,在编码完成后保存文件,文件拓展名“设计名称.c”,新文件创建完成;
(3)程序编译和调试:点击编译按键,让刚刚编写的代码运行,在下面的结果显示框中,可以看到运行是否正确与出现错误的地方[6],根据错误提示把代码修改成正确的,直到提示没有错误且实物功能均符合要求为止。
在编译程序的过程中,编译结果显示有两处错误,根据错误提示,发现在LCD12864初始化部分,源代码末尾没有加分号,加上分号之后,重新编译,结果没有错误。
还有一处错误是在连续三次输入错误密码,蜂鸣器报警部分,发现没有编写“BeepNum=10”,加上该部分代码后,重新编译,结果没有错误。
最后结果显示界面如图4.2所示。

图4.2 程序无错误显示图
4.3 实物调试
根据本设计预期实现功能,对实物进行调试
(1)LCD12864液晶显示屏显示刷卡是否成功与密码是否正确等状态;
(2)系统集成两种解锁方式:RFID卡解锁、密码解锁,在忘记带RFID卡时可通过密码进行解锁;
(3)刷卡之后,通过MFRC522读卡器可以读取到卡内的信息,信息匹配成功继电器吸合门锁打开,十秒左右会自动关闭门禁;如果匹配失败声光报警提醒;
(4)可以通过管理界面进行RFID卡的注册和注销,同时也可以进入管理界面,把原密码修改为新密码。
(5)4×4矩阵键盘定义,分别为数字键、进入管理键、切换上一项键、切换下一项键、退格键、确定键、返回上一级菜单键。
本设计的所有功能均能实现,实物如图4.3所示。

图4.3 设计实物图

结 论

通过分析做出总结,本次设计主要是由控制芯片STC89C52、射频接收模块RFID-RC522、AT24C02存储模块、显示屏LCD12864等组成的RFID门禁系统。本系统为人们的生活带来了极大的便利,并且提高了安全水平。它具有高安全性和强大的可扩展性,可用于公司或社区的一卡通扫描,避免了使用钥匙,节省了资源。这个设计既经济又划算,而且更加安全。本设计为生活提供了方便,实现了一个系统多张卡,而且可以随时注册和注销卡,使用方法简单方便。
本设计最终实现了预期的所有功能,具体实现的功能有:
(1)RFID卡的读取与注册注销;
(2)LCD12864显示门的状态;
(3)通过按键可输入密码;
(4)进行密码验证;
(5)修改密码;
(6)声光报警;
(7)电磁锁控制门的状态。
随着时代的进步和人民生活水平的提高,相信本设计提出的这种基于单片机的RFID门禁系统会被越来越多的家庭、社区、公共场所所应用;门禁系统会有更广阔的发展空间,在未来的生活中,门禁系统将会与各种网络系统连接在一起,由一张卡控制全部的系统,就是所谓的一卡通系统。

参考文献

[1] 杜永峰. 基于单片机的智能门禁系统设计[M]. 广东: 电子制作, 2019.3:10-13
[2] 刘志强. 基于单片机的宿舍门禁系统设计研究[M]. 江西: 中国高新区, 2017.6:21-25
[3] 周晓光. 射频识别技术原理与应用实例[M]. 北京: 人民邮电出版社, 2013.6:54-60
[4] 高福成. C程序设计教程[M]. 天津: 天津大学出版社, 2012.8:43-44
[5] 何宏. 单片机原理与接口技术[M]. 北京: 国防工业出版社, 2005.2:21-23
[6] 黄志伟. 射频电路设计[M]. 北京: 电子工业出版社社, 2015.4:22-28
[7] 朱勇. 单片机原理与应用技术[M]. 北京: 清华大学出版社, 2003.7:31-36
[8] 张义强. 无线射频识别技术规划与实施[M]. 北京: 电子工业出版社, 2011.6:13-15
[9] 陈国栋. 基于射频识别技术的门禁系统研究与设计[M]. 长沙: 中南大学, 2005.4:57-59
[10] 翟德旭. 基于射频卡技术的智能门禁系统[M]. 黑龙江: 黑龙江大学, 2012.8:26-27
[11] 张黎. 基于RFID的教室门禁系统的设计与实现[M]. 湖北: 华中师范大学, 2012.9:41-45
[12] 黄菊生. 基于智能IC卡的网络门禁系统设计与开发[M]. 长沙: 湖南大学, 2003.4:32-36
[13] 王爱英. 智能卡技术[M]. 北京: 清华大学出版社, 2000.7:24-29
[14] 贾林. 射频识别技术及其在物流交通领域的应用[J]. 交通世界, 2005,31(3):35-39
[15] 郑先峰. 基于RFID技术的无线门禁系统的设计[J]. 通信技术, 2009,22(3):51-53
[16] 周学叶. 基于RFID的门禁系统设计[J]. 安防科技, 2009,15(2):19-21
[17] 杜彬. 基于射频识别技术的门禁系统的研究与实现[J]. 机械工程与自动化, 2013,24(2):181-182
[18] 张洁. 基于RFID技术的智能门禁系统设计[M]. 河北: 河北科技大学, 2010.3:65-67
[19] 安静宇. 基于非接触式IC卡门禁系统的设计[M]. 西安: 西安科技大学, 2006.8:32-36
[20] 杨友文,王建华. 射频IC卡系统的应用[J]. 合肥工业大学学报(自然科学版), 2002,31(3):982-984
[21] 史纪元, 黄忠义. 智能门禁系统设计[J]. 潍坊学院学报, 2005,5(1):34-35
[22] 王汝琳. 智能门禁控制系统[M]. 北京: 电子工业出版社, 2004.5:53-56

附录1 总电路原理图

附录2 源程序代码

#include <reg52.h>
#include <intrins.h> //包含头文件
//#include <string.h>
//#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int //定义变量类型
#define nop() nop() //空操作指令 宏定义

uchar xdata shu[16]; //IC内容暂存数组变量
uchar xdata RevBuffer[4]; //IC卡的唯一序列号
uchar xdata IDH[4]; //当先检测的IC卡序列号
uchar code DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

#include “rc522.c” //调用控制检测文件

#include “SerialLcd12864.c” //调用控制检测文件
#include “24C02.h” //调用控制检测文件

sbit Door=P3^0;
sbit Beep=P2^0; //定义IO口

uchar code Pass[6]={1,3,1,4,2,0}; //定义万能密码数组

uint OperationTime; //定义变量
uchar ShowMode,HintMode,SetOption; //定义变量 ShowMode显示的模式,其实就是显示的状态
uchar ms,PassNum,OpenTime,BeepNum,ShowTime,Show3Time; //定义变量
uchar xdata SysPass[6],InputPass[6],NewPass[6],AgainPass[6]; //定义数组,系统密码数组、输入密码数组,新密码数组。再一次输入密码数组
uchar ResultShow,ErrorNum; //定义变量 ErrorNum错误次数

bit s1,ok,bj; //定义位变量

void delay(uint T) //短延时函数
{
while(T–);
}

void TimerConfig(void)
{
SCON= 0x50; //串口方式1 //REN=1; 允许接收
PCON=0x00; //SMOD=0
TMOD= 0x21; //定时器1定时方式2
TH1= 0xFD; //11.0592MHz 模块默认波特率为9600bps
TL1= 0xFD;
TR1= 1; //启动定时器
TH0=0x3c;
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
}

/*Fingerprint Code/

void show() // 12864液晶显示程序
{
uchar i; //定义局部变量
//ShowMode=6;
switch(ShowMode) // switch case语句,当 ShowMode=0,就会执行ShowMode=1;,==1,就会执行case 1;的语句
{
case 0:
ShowMode=1;
break;

	case 1:
	LCD12864_pos(1,2);	 //液晶控制写地址命令  	LCD12864_pos括号里有两个,第一个数据填写的是显示的第几行,第二个数据是显示这一行的第几个位置
	LCD12864_writebyte("欢迎使用");	  //显示字符串
	LCD12864_pos(2,1);				  //第二行第一个位置显示
	LCD12864_writebyte("多功能电子锁");	//显示字符串
	break;

	case 2:
	LCD12864_pos(0,1);	//第零行,第一个位置开始准备显示
	LCD12864_writebyte("密码输入开锁");	 //显示字符串
	LCD12864_pos(1,1);  //第一行第一个位置
	LCD12864_writebyte(" "); //显示空
	for(i=0;i<PassNum;i++) //这里是输入密码时显示星号设置
	{
		LCD12864_write(1,0x2a);	 //对于这个函数LCD12864_write,里面也是填写两个数据,第一个是0/1,只能填写0或者1,0代表命令,1代表数据,然后填写的数据是根据前面的数据命令来控制的,比如这个,0x2A就是数据
	}							 //显示部分基本就是这样,就不做过多的赘述
	if(s1==0&&PassNum<6) LCD12864_write(1,0x5f);  //显示数据下面的横杠
	else LCD12864_writebyte(" ");
	for(i=0;i<(6-PassNum);i++)	   //填充空格
	{
		LCD12864_writebyte(" ");	
	}
	break;
															    

	case 3:
//	HintMode=1;
	switch(HintMode)			//门状态switch case语句	  HintMode=0,就是门代开
	{
		case 0:
		LCD12864_pos(1,2);
		LCD12864_writebyte("门已打开");
		break;

		case 30:
		LCD12864_pos(1,2);
		LCD12864_writebyte("门已打开");	   // HintMode=1,就是门关闭
		LCD12864_pos(2,1);
		LCD12864_writebyte("ID:");		  //下下面显示门禁ID号
		for(i=0;i<4;i++)
		{
			if(IDH[i]/16<10)
			LCD12864_write(1,0x30+IDH[i]/16);
			else LCD12864_write(1,0x41+IDH[i]/16-10);
			if(IDH[i]%16<10)
			LCD12864_write(1,0x30+IDH[i]%16);
			else LCD12864_write(1,0x41+IDH[i]%16-10);
		}
		break;

		case 1:			   //显示密码状态
		LCD12864_pos(1,2);
		LCD12864_writebyte("密码错误");
		LCD12864_pos(2,1);
		LCD12864_writebyte("请再次输入!");

		break;


		case 3:			   //显示密码错误
		LCD12864_pos(1,2);
		LCD12864_writebyte("信息错误");
		LCD12864_pos(2,1);
		LCD12864_writebyte("ID:");	  ///显示ID号
		for(i=0;i<4;i++)
		{
			if(IDH[i]/16<10)
			LCD12864_write(1,0x30+IDH[i]/16);
			else LCD12864_write(1,0x41+IDH[i]/16-10);
			if(IDH[i]%16<10)
			LCD12864_write(1,0x30+IDH[i]%16);
			else LCD12864_write(1,0x41+IDH[i]%16-10);
		}
		break;

		case 4:			   //显示修改密码部分的错误信息显示
		LCD12864_pos(1,2);
		LCD12864_writebyte("密码错误");
		break;

		case 5:
		LCD12864_pos(1,2);
		LCD12864_writebyte("修改完成");
		break;

		case 6:
		LCD12864_pos(1,0);
		LCD12864_writebyte("新密码输入不一致");
		break;

		
		
	}
	break;

	case 4:
	//	SetOption=0;
		switch(SetOption)					 //首页面,功能操作选择界面   根据state的值显示选择不同的内容
		{									 //SetOption设置变量
			case 0:
				LCD12864_pos(0,0);
				LCD12864_writebyte("★");	//	→☆
				LCD12864_pos(1,0);
				LCD12864_writebyte("  ");
				LCD12864_pos(2,0);
				LCD12864_writebyte("  ");
			break;

			case 1:
				LCD12864_pos(1,0);
				LCD12864_writebyte("★");	//	→☆
				LCD12864_pos(0,0);
				LCD12864_writebyte("  ");
				LCD12864_pos(2,0);
				LCD12864_writebyte("  ");
			break;

		}
	
		LCD12864_pos(0,1);				    //4行显示选择内容
		LCD12864_writebyte("①密码设置");
		
		LCD12864_pos(1,1);	
		LCD12864_writebyte("②IC卡登记");		
	break;

	case 5:
	LCD12864_pos(0,2);
	LCD12864_writebyte("密码设置");		//设置密码部分
	LCD12864_pos(1,0);
	LCD12864_writebyte("原密码:");
	if(SetOption==0)
	{
		for(i=0;i<PassNum;i++)	   //显示星号
		{
			LCD12864_write(1,0x2a);
			//LCD12864_write(1,0x30+InputPass[i]);	
		}
		if(PassNum==0)
		{
			if(s1==0) LCD12864_write(1,0x5f); //显示数据下的横杠
			else LCD12864_writebyte(" ");
		}
		for(i=0;i<(6-PassNum);i++)
		{
			LCD12864_writebyte(" ");	
		}
	}
	LCD12864_pos(2,0);
	LCD12864_writebyte("新密码:");	   //显示新密码
	if(SetOption==1)
	{
		for(i=0;i<PassNum;i++)
		{
			LCD12864_write(1,0x2a);	  //星号
		}
		if(PassNum==0)
		{
			if(s1==0) LCD12864_write(1,0x5f); //横杠
			else LCD12864_writebyte(" ");
		}
		for(i=0;i<(6-PassNum);i++)
		{
			LCD12864_writebyte(" ");	
		}
	}
	LCD12864_pos(3,0);
	LCD12864_writebyte("再一次:");		//再次确定密码
	if(SetOption==2)
	{
		for(i=0;i<PassNum;i++)
		{
			LCD12864_write(1,0x2a);
		}							 
		if(PassNum==0)
		{
			if(s1==0) LCD12864_write(1,0x5f);
			else LCD12864_writebyte(" ");
		}
		for(i=0;i<(6-PassNum);i++)
		{
			LCD12864_writebyte(" ");	
		}
	}

	break;

	case 6:
	if(SetOption==0)
	{
		LCD12864_pos(0,2);
		LCD12864_writebyte("注册IC卡");		//设置状态里的,修改IC部分,注册、注销、
	}else
	{
		LCD12864_pos(0,2);
		LCD12864_writebyte("注销IC卡");
	}
	if(ResultShow==1)
	{
		LCD12864_pos(2,2);
		LCD12864_writebyte("注册完成");
		LCD12864_pos(3,1);
		LCD12864_writebyte("ID:");
		for(i=0;i<4;i++)
		{
			if(IDH[i]/16<10)
			LCD12864_write(1,0x30+IDH[i]/16);
			else LCD12864_write(1,0x41+IDH[i]/16-10);
			if(IDH[i]%16<10)
			LCD12864_write(1,0x30+IDH[i]%16);
			else LCD12864_write(1,0x41+IDH[i]%16-10);	//显示ID号
		}
	}else if(ResultShow==2)
	{
		LCD12864_pos(2,2);
		LCD12864_writebyte("注销完成");		//显示注册完成
		LCD12864_pos(3,1);
		LCD12864_writebyte("ID:");
		for(i=0;i<4;i++)
		{
			if(IDH[i]/16<10)
			LCD12864_write(1,0x30+IDH[i]/16);
			else LCD12864_write(1,0x41+IDH[i]/16-10);
			if(IDH[i]%16<10)
			LCD12864_write(1,0x30+IDH[i]%16);
			else LCD12864_write(1,0x41+IDH[i]%16-10);
		}
	}else if(ResultShow==3)
	{
		LCD12864_pos(2,2);
		LCD12864_writebyte("IC卡错误");		//IC卡刷卡错误
		LCD12864_pos(3,1);
		LCD12864_writebyte("ID:");
		for(i=0;i<4;i++)
		{
			if(IDH[i]/16<10)
			LCD12864_write(1,0x30+IDH[i]/16);
			else LCD12864_write(1,0x41+IDH[i]/16-10);
			if(IDH[i]%16<10)
			LCD12864_write(1,0x30+IDH[i]%16);
			else LCD12864_write(1,0x41+IDH[i]%16-10);
		}
	}else
	{
		LCD12864_pos(2,2);
		LCD12864_writebyte("        ");	
		LCD12864_pos(3,1);
		LCD12864_writebyte("            ");	
	}
	break;

	case 8:
	LCD12864_pos(1,1);
	LCD12864_writebyte("输入错误超限");	   //输入密码错误三次之后的显示界面
	LCD12864_pos(2,1);
	LCD12864_writebyte(" <键盘锁死> ");
	while(1);
	break;

	case 9:
	LCD12864_pos(0,0);
	LCD12864_writebyte("请输入密码");
	LCD12864_pos(1,1);
	LCD12864_writebyte(" ");
	for(i=0;i<PassNum;i++)
	{
		LCD12864_writebyte("*");	
	}
	if(s1==0&&PassNum<6) LCD12864_write(1,0x5f);
	else LCD12864_writebyte(" ");
	for(i=0;i<(6-PassNum);i++)
	{
		LCD12864_writebyte(" ");	
	}
	break;
}

}

uchar key_fs() //矩阵按键返回按码
{ //矩阵检测采用的是反转法
uchar fs=255,ptem;
P1=0x0f; //首先给IO口赋值
if(P1!=0x0f) //当IO口状态不对的时候,说明IO口有按下
{
delay(800); //短延时消抖
P1=0x0f; //再次赋值
if(P1!=0x0f) //再次判断按下,这时候如果通过,就说明是真的按下了
{
ptem=P1;//把当前的按键值赋给 ptem变量,这时候得到一个数据
P1=0xf0; //然后再给按键进行赋值,注意,这时候赋值的是高四位,之前是低四位,这时候就会得到一个不一样的数据
ptem=ptem|P1; //将这两个数据进行按位或,就会得到一个新的数据,这样就可以判断是哪个按键按下了
switch (ptem) //找按键值,
{
case 0xe7: //如果按键值是0xe7,那么就使得fs=1;下面的一样
fs=1;
break;
case 0xd7:
fs=2;
break;
case 0xb7:
fs=3;
break;
case 0x77:
fs=10;
break;
case 0xeb:
fs=4;
break;
case 0xdb:
fs=5;
break;
case 0xbb:
fs=6;
break;
case 0x7b:
fs=11;
break;
case 0xed:
fs=7;
break;
case 0xdd:
fs=8;
break;
case 0xbd:
fs=9;
break;
case 0x7d:
fs=12;
break;
case 0xee:
fs=13;
break;
case 0xde:
fs=0;
break;
case 0xbe:
fs=14;
break;
case 0x7e:
fs=15;
break;
}
P1=0x0f;
while(P1!=0x0f) //按键释放,其实没用,可以删掉
{
P1=0x0f;
}
}
}
return(fs); //返回fs的值
}

/**********************************************
按键控制函数
**********************************************/
void ButtonCode()
{
uchar Button_ID,i; //按键返回的键值 、 循环计数变量
Button_ID=key_fs(); //读取按键键值
if(Button_ID!=255) //如果按键按下 Button_ID 不等于255 说明有按键按下
{
Beep=0; //按键按下蜂鸣器提示音
ms=7;
OperationTime=300; //按键操作等待时间 “如果按键一段时间没有操作,则返回主界面”
if(ShowMode0||ShowMode3) //判断系统状态 如果是初始化界面 或者 提示信息界面 按下按键 则返回主界面
{
LCD12864_Qing();
ShowMode=1;
}else //否则 则执行按键功能呢
{
if(Button_ID<10) //判断按键按下的是否是数字按键 0-9的数字按键对应Button_ID 0-9
{
switch(ShowMode) // 区分判断系统模式 不同的系统模式对应不同的功能
{
case 2: //如果是输入密码模式
if(PassNum<6) //一共输入6位密码
{
InputPass[PassNum]=Button_ID; //将数字按键对应的数据存入 ‘输入密码数组’中
PassNum++; //密码已输入位数加1
}
break;

				case 5:		//如果系统模式为修改密码模式
				if(SetOption==0)   //判断当前出入的密码类型  ‘旧密码’‘新密码’‘再次输入’
				{
					if(PassNum<6)  //一共输入6位密码
					{
						InputPass[PassNum]=Button_ID; //将数字按键对应的数据存入 ‘输入密码数组’中
						PassNum++;	 	//密码已输入位数加1
					}
				}else if(SetOption==1)
				{
					if(PassNum<6)  //一共输入6位密码
					{
						NewPass[PassNum]=Button_ID;	 //将数字按键对应的数据存入 ‘新密码数组’中
						PassNum++;	  	//密码已输入位数加1
					}
				}else if(SetOption==2)
				{
					if(PassNum<6)  //一共输入6位密码
					{
						AgainPass[PassNum]=Button_ID;  //将数字按键对应的数据存入 ‘再次输入密码数组’中
						PassNum++;		//密码已输入位数加1
					}
				}
				
				break;

				
				case 9:	  //如果系统模式为进入设置页面输入密码模式
				if(PassNum<6)//一共输入6位密码
				{
					InputPass[PassNum]=Button_ID;		//将数字按键对应的数据存入 ‘输入密码数组’中
					PassNum++;	  	//密码已输入位数加1
				}
				break;

				case 1:	  //如果系统模式为初始化模式
				LCD12864_Qing();   //LCD12864初始化
				ShowMode=2;		// 跳转输入密码模式
				SetOption=0;	//设置选项清0
				PassNum=0;	   //输入密码位数清0
				if(PassNum<6) //一共输入6位密码
				{
					InputPass[PassNum]=Button_ID;  //将数字按键对应的数据存入 ‘输入密码数组’中
					PassNum++;	 	//密码已输入位数加1
				}
				break;
			}
		}else	//如果按键输入非数字按键(按下按键为控制按键)
		{
			switch(Button_ID)  //判断按键的键码  以及对应的按键功能
			{
				case 10:		 //选项切换按键   上
				switch(ShowMode)   //根据模式切换设置选项
				{
					case 4:	  //系统设置页面切换选择项
					if(SetOption==0) SetOption=1;
					else SetOption--;
					break;
						
					case 6:	   //系统IC卡设置页面  切换功能
					if(SetOption==0)  SetOption=1;
					else  SetOption=0;
					break;

				}
				break;
				
				case 11:	  //选项切换按键   下
				switch(ShowMode)   //根据模式切换设置选项
				{
					case 4:	 //系统设置页面切换选择项
					SetOption=(SetOption+1)%2;
					break;
	
					case 6:	    //系统IC卡设置页面  切换功能
					if(SetOption==0)  SetOption=1;
					else  SetOption=0;
					break;

				}
				break;

				case 12:	 //系统返回按键
				switch(ShowMode)
				{		
					case 2:	   //返回系统主界面
					LCD12864_Qing();	//LCD12864初始化
					ShowMode=1;	
					SetOption=0;	 //设置选项变量清0
					break;
					
					case 3:	   //返回系统主界面
					LCD12864_Qing();//LCD12864初始化
					ShowMode=1;	
					SetOption=0;	//设置选项变量清0
					break;
					
					case 4:	  //返回系统主界面
					LCD12864_Qing(); //LCD12864初始化
					ShowMode=1;	
					SetOption=0;	//设置选项变量清0
					break;
					
					case 5:	   //返回设置主界面
					LCD12864_Qing(); //LCD12864初始化
					ShowMode=4;	
					SetOption=0;	//设置选项变量清0
					break;
					
					case 6:	//返回设置主界面	
					LCD12864_Qing(); //LCD12864初始化
					ShowMode=4;	 
					SetOption=0;   //设置选项变量清0
					break;
					
					
					case 9:	   //返回系统主界面
					LCD12864_Qing(); //LCD12864初始化
					ShowMode=1;	
					SetOption=0;   //设置选项变量清0
					break;
					


				}
				break;

				case 13:	 //输入内容撤销
				if(PassNum!=0)	 //如果按键输入位数不等于0 ,
				{
					InputPass[PassNum]=0; //则清除当前输入密码的数组
					PassNum--;			  //密码输入位数-1
				}else if(SetOption>0) 	  //如果输入密码位数为0  是   如果设置变量不等于0   则变量减1  (此处理用于修改密码  撤销输入内容处理)
				{
					SetOption--;		
				}
				break;

				case 14: //系统确认按键
				switch(ShowMode) //系统模式判断
				{
					case 2:	  //如果是输入密码模式
					for(i=0;i<PassNum;i++)	 //比较输入的密码  与  系统密码是否对应
					{
						if(SysPass[i]!=InputPass[i])  
						{
							break;		//则跳出循环
						}
					}								  
					if(i==6)	//如果6位密码都相同	    则提示门已打开提示
					{
						LCD12864_Qing();	//初始化
						ShowMode=3;			//显示对应的提示信息
						Show3Time=3;
						SetOption=0;	
						HintMode=0;
						OpenTime=5;		   //开门倒计时赋值
						ErrorNum=0;
					}else			//如果密码错误
					{
						for(i=0;i<PassNum;i++)//再次判断与6位万能密码是否相同
						{
							if(Pass[i]!=InputPass[i])  //如果密码不同
							{
								break;	 //则跳出循环
							}
						}
						if(i==6)   	//如果6位密码都相同	    则提示门已打开提示
						{
							LCD12864_Qing();  //初始化
							ShowMode=3;		 	//显示对应的提示信息
							Show3Time=3;
							SetOption=0;	
							HintMode=0;
							OpenTime=5;		  //开门倒计时赋值
							ErrorNum=0;
						}else		   //如果万能密码比对码错误
						{
							LCD12864_Qing(); //初始化
							ShowMode=3;	
							Show3Time=3;	  //提示密码出入错误
							SetOption=0;	
							HintMode=1;
							ErrorNum++;		 //密码错误次数+1
							if(ErrorNum>2)	  //如果密码错误3次
							{
								LCD12864_Qing();  //LCD12864初始化
								ShowMode=8;		 //调整密码锁死界面   并报警
								BeepNum=10;	
							}
						}
					}
					break;

					case 4:	   //系统为设置页面模式
					if(SetOption==0)  //判断设置选项
					{
						LCD12864_Qing();   //LCD12864初始化
						ShowMode=5;			//跳转密码修改界面
						SetOption=0;	
						PassNum=0;
					}else if(SetOption==1)
					{
						LCD12864_Qing();  //LCD12864初始化
						ShowMode=6;		 //跳转IC 设置页面
						SetOption=0;
						ResultShow=0;	
					}
					break;
					case 5:	   //修改密码界面
					if(SetOption<2)		//	如果3组密码没有输入完成   则切换下一组进行输入  ‘旧密码’‘新密码’‘再一次’
					{
						SetOption++;
						PassNum=0;
					}else	//如果3组密码输入完成,  则开始比较密码输入数据
					{
						for(i=0;i<PassNum;i++)	  //比较输入的旧密码密码  与  系统密码是否对应
						{
							if(SysPass[i]!=InputPass[i])  //如果密码不同
							{
								break;			    //则跳出循环
							}
						}
						if(i==6) //如果面输入正确
						{
							for(i=0;i<PassNum;i++)	  //比较输入的新密码  与  再一次输入的密码数据是否对应
							{
								if(NewPass[i]!=AgainPass[i])  //如果不同
								{
									break;		 //则跳出循环
								}
							}
							if(i==6)  //如果输入的6位新密码相同  则将新密码赋值为系统密码,并保存24C02存储单元中
							{
								SysPass[0]=NewPass[0];		   //将新密码赋值为系统密码
								SysPass[1]=NewPass[1];
								SysPass[2]=NewPass[2];
								SysPass[3]=NewPass[3];
								SysPass[4]=NewPass[4];
								SysPass[5]=NewPass[5];		 //将新密码赋值为系统密码
								Write_dat_24C02(NewPass,0,6);//保存24C02存储单元中
								LCD12864_Qing(); //LCD12864初始化
								ShowMode=3;		 //跳转显示界面  显示提示内容
								Show3Time=3;
								SetOption=0;	
								HintMode=5;
							}else
							{
								LCD12864_Qing();  //LCD12864初始化
								ShowMode=3;	 	 //跳转显示界面  显示提示内容
								Show3Time=3;	  //提示输入错误
								SetOption=0;	
								HintMode=6;
							}	
						}else	//如果密码
						{
							for(i=0;i<PassNum;i++)	//比较输入的旧密码  与  系统万能密码是否对应
							{
								if(Pass[i]!=InputPass[i])   //如果不同
								{
									break;	 //则跳出循环
								}
							}
							if(i==6)  //如果6位密码相同
							{
								for(i=0;i<PassNum;i++)	   //比较输入的新密码  与  再一次输入的密码数据是否对应
								{
									if(NewPass[i]!=AgainPass[i])   //如果密码不同
									{
										break;	   //则跳出循环
									}
								}
								if(i==6)  //如果输入的6位新密码相同  则将新密码赋值为系统密码,并保存24C02存储单元中
								{
									SysPass[0]=NewPass[0];		   //将新密码赋值为系统密码
									SysPass[1]=NewPass[1];
									SysPass[2]=NewPass[2];
									SysPass[3]=NewPass[3];
									SysPass[4]=NewPass[4];
									SysPass[5]=NewPass[5];		 //将新密码赋值为系统密码
									Write_dat_24C02(NewPass,0,6);//保存24C02存储单元中
									LCD12864_Qing(); //LCD12864初始化
									ShowMode=3;		 //跳转显示界面  显示提示内容
									Show3Time=3;
									SetOption=0;	
									HintMode=5;
								}else
								{
									LCD12864_Qing();  //LCD12864初始化
									ShowMode=3;	 	 //跳转显示界面  显示提示内容
									Show3Time=3;	  //提示输入错误
									SetOption=0;	
									HintMode=6;
								}
							}else
							{
								LCD12864_Qing();  //LCD12864初始化
								ShowMode=3;		  //跳转显示界面  显示提示内容
								Show3Time=3;	  //提示信息输入错误
								SetOption=0;	
								HintMode=4;
							}
						}	
					} 
					break;

					case 9:
					for(i=0;i<PassNum;i++)	 //比较输入的密码  与  系统密码是否对应
					{
						if(SysPass[i]!=InputPass[i])  	 //如果密码不同
						{
							break;		//则跳出循环
						}
					}
					if(i==6)  //如果输入的6位新密码相同 
					{
						LCD12864_Qing();  //LCD12864初始化
						ShowMode=4;		  //则调整系统设置页面
						SetOption=0;
					}else  //如果密码输入不正确 ,  则判断系统万能密码
					{
						for(i=0;i<PassNum;i++)	   //比较输入的密码  与  系统密码是否对应
						{
							if(Pass[i]!=InputPass[i])	 //如果密码不同
							{
								break;	 //则跳出循环
							}
						}
						if(i==6)
						{
							LCD12864_Qing();  //LCD12864初始化
							ShowMode=4;		  //跳转系统设置页面
							SetOption=0;
						}else
						{
							LCD12864_Qing();  //LCD12864初始化
							ShowMode=3;		  //跳转显示界面  显示提示内容
							Show3Time=3;
							SetOption=0;	
							HintMode=4;
						}
					}
					break;

				}
				break;

				case 15: //系统进入设置页面控制按键
				if(ShowMode==1)
				{
					LCD12864_Qing();   //LCD12864初始化
					ShowMode=9;		   //进入系统设置模式的密码输入界面
					PassNum=0;
				}
				break;
			}
		}
	}
}

}

void zuce(void) //注册
{
char status;
PcdReset(); //复位
status=PcdRequest(PICC_REQIDL,&RevBuffer[0]);//寻天线区内未进入休眠状态的卡,返回卡片类型 2字节
if(status!=MI_OK)
{
bj=0;
// ResultShow=3;
return;
} // http://find.qq.com/index.html?version=1&im_version=5389&width=910&height=610&search_target=0#
status=PcdAnticoll(&RevBuffer[0]);//防冲撞,返回卡的序列号 4字节
if(status!=MI_OK)
{
return;
}
IDH[0]= RevBuffer[0]; //赋值给序列号显示数组对应的序列号
IDH[1]= RevBuffer[1];
IDH[2]= RevBuffer[2];
IDH[3]= RevBuffer[3];
status=PcdSelect(&RevBuffer[0]); //选卡部分
if(status!=MI_OK)
{
return;
}
status = PcdAuthState(0x61,63,DefaultKey,&RevBuffer[0]);// 校验卡密码B
if(status!=MI_OK)
{
return;
}
status=PcdRead(60,&shu[0]); //读取IC卡中的数
shu[0]=66;
status=PcdWrite(60,&shu[0]); //写入IC卡中的数
if(bj==0) //按键每一次按下的提示音
{
bj=1;
Beep=0;
ms=5;
ResultShow=1;
ShowTime=2;
}

}

void qingchu(void) //清楚卡号
{
char status;
PcdReset(); //复位
status=PcdRequest(PICC_REQIDL,&RevBuffer[0]);//寻天线区内未进入休眠状态的卡,返回卡片类型 2字节
if(status!=MI_OK)
{
bj=0;
// ResultShow=3;
return;
} // http://find.qq.com/index.html?version=1&im_version=5389&width=910&height=610&search_target=0#
status=PcdAnticoll(&RevBuffer[0]);//防冲撞,返回卡的序列号 4字节
if(status!=MI_OK)
{
return;
}
IDH[0]= RevBuffer[0]; //赋值给序列号显示数组对应的序列号
IDH[1]= RevBuffer[1];
IDH[2]= RevBuffer[2];
IDH[3]= RevBuffer[3];
status=PcdSelect(&RevBuffer[0]); //选卡部分
if(status!=MI_OK)
{
return;
}
status = PcdAuthState(0x61,63,DefaultKey,&RevBuffer[0]);// 校验卡密码B
if(status!=MI_OK)
{
return;
}
status=PcdRead(60,&shu[0]); //读取IC卡中的数
shu[0]=0;
status=PcdWrite(60,&shu[0]); //写入IC卡中的数
if(bj==0) //按键每一次按下的提示音
{
bj=1;
Beep=0;
ms=5;
ResultShow=2;
ShowTime=2;
}

}

void jiance(void) //判断是否开门
{
char status;
PcdReset(); //复位
status=PcdRequest(PICC_REQIDL,&RevBuffer[0]);//寻天线区内未进入休眠状态的卡,返回卡片类型 2字节
if(status!=MI_OK)
{
bj=0;
ok=0;
return;
} // http://find.qq.com/index.html?version=1&im_version=5389&width=910&height=610&search_target=0#
status=PcdAnticoll(&RevBuffer[0]);//防冲撞,返回卡的序列号 4字节
if(status!=MI_OK)
{
return;
}
IDH[0]= RevBuffer[0]; //赋值给序列号显示数组对应的序列号
IDH[1]= RevBuffer[1];
IDH[2]= RevBuffer[2];
IDH[3]= RevBuffer[3]; //赋值给序列号显示数组对应的序列号
status=PcdSelect(&RevBuffer[0]); //选卡部分
if(status!=MI_OK)
{
return;
}
status = PcdAuthState(0x61,63,DefaultKey,&RevBuffer[0]);// 校验卡密码B
if(status!=MI_OK)
{
return;
}
status=PcdRead(60,&shu[0]); //读取IC卡中的数
if(ok==0)
{
ok=1;

	if(shu[0]==66)	   //如果IC卡中的数据为66   则判断为正确
	{
		ShowMode=3;	
		Show3Time=3;
		SetOption=0;	
		HintMode=30;
		OpenTime=5;	
	}else		 //否则
	{
		ShowMode=3;	
		Show3Time=3;
		SetOption=0;	
		HintMode=3;	
	}
	LCD12864_Qing();
	OperationTime=60;
}
if(bj==0)		   //按键每一次按下的提示音
{
	bj=1;
	Beep=0;
	ms=7;
}				 

}

void main()
{
TimerConfig(); //初始化定时器
LCD12864_init(); //12864初始化
Read_dat_24C02(SysPass,0,6); //读取密码数据
if(SysPass[0]>9||SysPass[1]>9||SysPass[2]>9||SysPass[3]>9||SysPass[4]>9||SysPass[5]>9)
{
SysPass[0]=SysPass[1]=SysPass[2]=SysPass[3]=SysPass[4]=SysPass[5]=0;
} //判断读取的数据是否正确,不正确就赋值000000
ShowMode=1;//置一
while(1)
{
ButtonCode(); //按键处理函数
show(); //显示处理函数
if(ShowMode6&&SetOption0) //调用门禁处理
{
zuce(); //门禁数据处理
}else if(ShowMode6&&SetOption1)
{
qingchu(); //清除函数
}
if(ShowMode1)
{
jiance(); //ID号检测
}
if(ShowMode!=1&&OperationTime
0)
{
ShowMode=1;
LCD12864_Qing(); //12864清屏
}
if(OpenTime>0)
{
Door=0;
}else
{
Door=1;
}
if(ShowTime0&&(SetOption!=2||(ResultShow!=5&&ResultShow!=6&&ResultShow!=7))) ResultShow=0;
if(ShowMode
3&&Show3Time==0)
{
ShowMode=1;
LCD12864_Qing();
}
}
}

void Timer0IntCode() interrupt 1 //定时器 0
{
TH0=0x3c;
TL0=0xb0; //重新装载初值 50ms
ms++; //ms每隔50毫秒进行一次加一
if(ms%10==0) //当ms取余等于0的时候
{
s1=!s1; //标志位取反
if(BeepNum>0) //只要蜂鸣器报警次数不为0
{
Beep=!Beep;//蜂鸣器取反,实现滴滴滴
BeepNum–; //数据减减
}else
{
Beep=1; //报警次数为0蜂鸣器关闭
}
}
if(ms>19)//ms》19的时候就是20,那么,20*50=1000,也就是1秒定时
{
ms=0; //ms=0; 清零这个数据 重新1秒定时
if(OperationTime>0) OperationTime–;
if(OpenTime>0) OpenTime–;
if(ShowTime>0) ShowTime–;
if(Show3Time>0) Show3Time–; //这几个数据只要不为0,就自减
}
}

致 谢

在这次毕业设计中,由于经验的缺乏,难免有许多考虑不周全的地方,如果没有指导老师的督促指导,以及同学们的帮助,想要完成这个设计的难度是极大的。
在这里首先要感谢我的指导老师沈洪洋老师和台闯老师。从课题确定开始,查阅资料,开题报告以及任务书的确定和修改,中期检查,后期详细设计,甚至最后论文编写和完成答辩稿,整个过程中都给予了我悉心的指导。在此,特别向沈洪洋老师和台闯老师表示由衷的感谢和诚挚的敬意。
其次还要感谢我的任课教师和系主任,正是因为有了他们细心、严格的教导,我才能学到许多专业知识以及提升自身的潜力。我还要感谢我的班主任赵老师以及辅导员杨老师这几年对我的帮助、关心与教导。最后还要感谢大学四年来所有的老师,为我打下扎实的专业知识基础,让我在遇到那些专业问题时不至于不知所措。同时还要感谢所有的同学们,正是有了你们的陪伴,大学四年才会过的如此精彩;正是有了你们的帮助,此次毕业设计才会顺利完成。
回首大学四年,我们一起走过的路,有过欢笑也有过泪水,我相信大学四年必将成为我生命中最重要、最难忘的一个阶段。因此,我感谢学校对我的悉心培养和正确引导;在今后的工作中,我将以此为动力,用实际行动来报答母校、来证明自己。
最后,在此,向全体论文评阅和答辩委员会的老师们致以最诚挚的谢意!预祝母校沈阳城市学院发展日新月异,培养出更高层次的人才!

作者:qq1744828575

物联沃分享整理
物联沃-IOTWORD物联网 » 基于单片机的RFID门禁系统设计与实现

发表评论