基于单片机的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