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

概要

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

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

一、控制系统设计

1 项目总体设计

  本项目基于单片机的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卡信息和按键输入信息进行处理,经转换后传输给步进电机驱动电路、液晶显示电路、报警电路,完成系统的运行。

二、总电路图设计

本设计采用STC89C52单片机作为主控制器,包括LCD12864液晶显示电路、射频识别电路、报警电路、按键电路、继电器驱动电路以及电源电路[4]

在这里插入图片描述

三、项目软件设计

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

图3.3 系统程序总体流程图

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

图4.3 设计实物图

程序

#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(ShowMode==0||ShowMode==3)	  //判断系统状态     如果是初始化界面 或者  提示信息界面  按下按键  则返回主界面
		{
			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(ShowMode==6&&SetOption==0)  //调用门禁处理
		{
			zuce();		 //门禁数据处理
		}else if(ShowMode==6&&SetOption==1)
		{
			qingchu();	//清除函数
		}
		if(ShowMode==1)
		{
			jiance();	//ID号检测
		}
		if(ShowMode!=1&&OperationTime==0)
		{
			ShowMode=1;																																				 
			LCD12864_Qing();   //12864清屏
		}
		if(OpenTime>0)
		{
			Door=0;
		}else
		{
		 	Door=1;
		}
		if(ShowTime==0&&(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,就自减
	}	
}





四、 结论

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

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 基于51单片机RFID门禁系统设计与实现如下: 首先,我们需要使用RFID读卡器与51单片机进行连接。读卡器负责读取RFID卡中的信息,并将其发送给51单片机进行处理。读卡器通过串口与51单片机进行通信,我们需要在51单片机上设置一个串口接收中断程序来接收读卡器发送的信息。 接下来,我们需要设计一个电子锁控制电路,并与51单片机进行连接。当51单片机接收到有效的RFID卡信息后,根据预先存储的卡号数据进行比对,如果匹配成功,则向电子锁控制电路发送开锁信号。 为了方便管理和配置,我们可以在系统中加入一个LCD液晶显示屏和按键输入。液晶显示屏负责显示系统状态以及对系统进行配置,按键输入可以用于对系统的配置和设置。 在51单片机程序设计方面,我们需要编写一个主程序来进行系统的初始化和各个模块的控制。主程序中需要包含串口接收中断程序、RFID卡数据的存储和比对程序、电子锁控制程序、液晶显示程序以及按键输入程序。通过合理的编程设计,将各个模块进行有机的组合,实现一个完整的RFID门禁系统。 在系统的使用方面,当RFID卡靠近读卡器时,读卡器将读取到RFID卡中的信息,并发送给51单片机进行处理。51单片机根据预先存储的卡号数据进行匹配,如果匹配成功,则发送开锁信号给电子锁控制电路,从而实现开门操作。系统的操作状态和配置信息可以通过液晶显示屏和按键输入进行查看和修改。 综上所述,基于51单片机RFID门禁系统设计与实现需要连接RFID读卡器、电子锁控制电路、LCD液晶显示屏和按键输入,并在51单片机程序中进行各个模块的初始化和控制。通过合理的设计和编程,可以实现一个方便实用的RFID门禁系统。 ### 回答2: 基于51单片机RFID门禁系统设计与实现旨在实现对特定区域的权限管理和安全控制。系统主要由三个部分组成:RFID读卡器、控制器和电磁锁。 首先,设计RFID读卡器可以通过读取RFID标签上的唯一标识来区分不同的用户。读卡器通过串口将读取到的卡号发送给控制器。 其次,设计控制器用于验证卡号的有效性并判断用户是否有权限进入。控制器通过与存储卡号的数据库进行比对,确定用户是否具有合法权限。如果权限验证通过,则控制器会发送开锁信号给电磁锁。 最后,实现电磁锁的控制,对门的状态进行控制。当控制器接收到验证通过的信号后,会发送一个电平信号到电磁锁,解除其锁定状态,用户就可以进入特定区域。 在系统的设计与实现中,需要注意以下几点:首先,RFID读卡器要具备读取RFID标签的能力,并通过串口将读取到的卡号传递给控制器。其次,控制器要能够和数据库进行交互,进行权限验证的操作。最后,电磁锁要具备可靠的控制性能,确保门的安全状态。 除了上述基本功能之外,还可以根据具体需求进行功能扩展,如添加报警系统、远程监控等,增强门禁系统的安全性和管理性。同时,采用51单片机进行设计与实现,既具备足够的性能和灵活性,又具有低功耗和成本较低的优势。 总之,基于51单片机RFID门禁系统设计与实现,能够实现对特定区域的权限管理和安全控制,为用户提供安全、便捷的出入管理服务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值