基于51单片机的指纹密码锁
主程序部分
/*头文件*/
#include <reg52.h>
#include <intrins.h>
#include "LCD12864.h"
#include "at24c02.h"
/*定义特殊端口,和特殊寄存器*/
#define buffer1ID 0x01
#define buffer2ID 0x02
#define confirm 0x88
#define quit 0x84
#define backspace 0x82
/*定义用户*/
#define user 1
void begin();
sbit B0=B^0;
sbit B7=B^7;
sbit k2=P3^7;
sbit jidianqi=P3^6;
sbit feng=P2^0;
/*定义全局变量*/
extern unsigned char times[];
unsigned char member=1,sec;
unsigned char errorcount;
unsigned char code buffer[user][6]=
{
{"000000"}
} ;
unsigned char dz[4];
unsigned char time[4];
unsigned char password[6];
unsigned char passwordid[6]={1,2,3,4,5,6};
unsigned char address1=20,tempx=20;
unsigned char address2=20;
unsigned char data K; /*K代表按下后产生的数字*/
unsigned char data key; /*key代表按键电位情况*/
unsigned int pageid;
unsigned char data confirmcode=11;
unsigned char sum[2];
int summaf,summas;
unsigned char xdata userpassword[7]={0};//用来储存正确的密码
unsigned char xdata fingerprint_holder[16]={0};//用来储存正确的指纹
/*定义延时函数*/
void delayms(unsigned int t)
{
unsigned int i,j;
for(i=t;i>0;i--);
for(j=110;j>0;j--);
}
/*定义指纹脉冲相关函数*/
void redray_init(void);
#include "zhiwen.h"
unsigned char redray_change(unsigned char rednum);
/*第一部分-硬件功能定义*/
/*第一部分-第一模块
串行通信模块,对单片机串口进行初始化。*/
//设置串口
void UsartConfiguration()
{
SCON=0x50; //设置为工作方式1 //REN=1 允许接收
TMOD=0x21; //设置计数器工作方式2
PCON=0x00; //SMOD=1 波特率加倍
TH1=0xFD; //计数器初始值设置,波特率9600
TL1=0xFD;
TR1=1; //打开总中断
EA=1; //打开计数器
}
/*第一部分-第二模块
矩阵键盘模块,这里采取整体扫描。*/
//整体扫描
void keyboard(unsigned char key)
{
if(key!=0)//倘若按下了,也就是说有m输入,m不为零
{
switch(key)
{
case(0x11):K=1;break;
case(0x21):K=2;break;
case(0x41):K=3;break;
case(0x81):K='A';break;
case(0x12):K=4;break;
case(0x22):K=5;break;
case(0x42):K=6;break;
case(0x82):K=34;break;
case(0x14):K=7;break;
case(0x24):K=8;break;
case(0x44):K=9;break;
case(0x84):K='C';break;
case(0x18):K='*';break;
case(0x28):K=0;break;
case(0x48):K=11;break;
case(0x88):K='D';break;
default:break;
}
}
}
unsigned char keyscan(void)
{
unsigned char rowcode,colcode;
P1=0xf0;
if((P1&0xf0)!=0xf0)//有键按下
{
delayms(1);//延时去按键抖动
if((P1&0xf0)!=0xf0)//再次检测
{
rowcode=0xfe;
while((rowcode&0x10)!=0)//逐行扫描初值
{
P1=rowcode;//输出行扫描码
if((P1&0xf0)!=0xf0)//本行有键按下。
{
colcode=(P1&0xf0)|0x0f;
while((P1&0xf0)!=0xf0)//按键释放
return ((~rowcode)+(~colcode)); //返回键的编码
}
else
rowcode=(rowcode<<1)|0x01; //行扫描码左移一位
}
}
}
return 0;
}
/*这两部分用额外的函数模块写在外部文件里面。*/
/*第一部分-第三模块
LCD12864函数集成模块,采用的是并行写法。
具有显示,清除文字,清除图片等功能。*/
/*第一部分-第四模块
AT24C02芯片部分,是用作存储密码的。*/
/*第二部分功能实现
第二部分-第一模块:在部分库中检查密码是否正确,正确返回1,错误返回0*/
unsigned char check(unsigned char user_password)
{
unsigned char flag,i,temp[6],address;
address=user_password*10;
for(i=0;i<6;i++)//密码规定6位,故读到第六位就可以了
{
temp[i]=readoutrom(address);
delayms(10);
address++;
}
for(i=0;i<6;i++)
{
if(temp[i]==userpassword[i])
flag=1;
else
flag=0;
}
return flag;
}
/*在全体库中检测密码是否正确*/
unsigned char password_check()
{
unsigned char i=0;
while(i<user)
{
if(check(i)==1)
{
member=i+1;
return 1;
}
i++;
}
return 0;
}
/*第二部分-第三模块:手动开锁*/
void use_hand()
{
lcdcleartxt();//在每次显示新的内容前,先清屏
lcddisplay_string(1,2,"门已开启");
jidianqi=0;
delayms(2500);
jidianqi=1;
lcddisplay_string(3,0,"按任意键继续");
while(keyscan()==0);
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
}
/*第二部分-第二模块
输入密码后开锁的判断*/
void use_password()
{
unsigned char i,j=0,x=1;
unsigned char flag1;
lcdcleartxt();
lcddisplay_string(1,0,"请输入密码开锁:");
for(i=0;i<6;i++)password[i]=0;
key=keyscan();
while(key!=confirm)
{
key=keyscan();
keyboard(key);
delayms(30);
if(key==0)K=10;
if((K>=0)&&(K<=9))
{
password[j]=K;
if(j<6)
{
lcdwritecommand(0x89+j);//指定第三行为显示密码输入的空位
lcdwrite(0x0f);
}
++j;
if(j==7)
j=6;
}//lcd12864并行显示
if(K==34)//按了删除键
{
if(j==0)
{
lcdwritecommand(0x89); //指定第三行为显示密码输入的空位
lcdwrite(0x20);
}
else
{
--j;
lcdwritecommand(0x89+j);//指定第三行为显示密码输入的空位
lcdwrite(0x20);
}
}
}
lcdcleartxt();
for(i=0;i<6;i++)
{
userpassword[i]=password[i]+0x30;
}
if(j==6)
{
flag1=password_check();
}
if(flag1==1&&errorcount<3)//判断输入是否合规
{
flag1=0;
use_hand();
errorcount=0;//错误次数归零
feng=1;
for(i=0;i<6;i++)password[i]=0;
}
else
{
if(errorcount<3)//如果密码错误次数小于3次
{
errorcount++;
lcddisplay_string(1,2,"密码错误");
lcddisplay_string(2,0,"还有 次尝试");
lcddisplay_string(3,0,"按任意键继续");
lcdwritecommand(0x8a);
lcdwrite(' ');
lcdwrite(3-errorcount+0x30);
}
if(errorcount==3)
{
feng=0;
lcdcleartxt();
lcddisplay_string(1,0,"已锁死");
lcddisplay_string(2,0,"请使用指纹");
}
delayms(1000);
}
key=0;
lcdcleartxt();
}
/*第二部分-第三模块:输入指纹后的开锁判断*/
void use_fingerprint()
{
unsigned char ids1,ids2,ids3;
lcdcleartxt();
lcddisplay_string(1,1,"请按手指开锁");
SFG_identify();
while(confirmcode==2)
SFG_identify();
if(confirmcode==0)
{
lcdcleartxt();
lcddisplay_string(1,2,"门已打开");
ids1=pageid/100;
ids2=pageid/10%10;
ids3=pageid%10;
lcddisplay_string(2,1,"编号为");
lcdwritecommand(0x8d);
lcdwrite(0x30+ids1);
lcdwrite(0x30+ids2);
lcdwrite(0x30+ids3);
errorcount=0;
feng=1;
jidianqi=0;
delayms(2500);
jidianqi=1;
}
else if(confirmcode==9)
{
lcdcleartxt();
lcddisplay_string(1,1,"没找到该指纹");
lcddisplay_string(2,1,"请重新按压");
errorcount=3;
feng=0;
}
else
{
lcdcleartxt();
lcddisplay_string(1,1,"接受器出错");
}
delayms(2000);
}
/*第二部分-第四模块:修改指纹,分为添加指纹和删除指纹*/
void addfingerprint()
{
unsigned char ida1,ida2,ida3;
lcdcleartxt();
lcddisplay_string(1,2,"请输入指纹");
SFG_getimage();
while(confirmcode!=0)
SFG_getimage();
SFG_genchar(buffer1ID);
UsartConfiguration();
SFG_fastsearch(buffer1ID);
while(confirmcode==1)
SFG_fastsearch(buffer1ID);
if(confirmcode==0)
{
lcdcleartxt();
lcddisplay_string(1,1,"");
lcddisplay_string(3,0,"");
while(keyscan()==0);
}
else if(confirmcode==9)
{
lcdcleartxt();
lcddisplay_string(1,1,"请再次输入指纹");
SFG_enroll();
while(confirmcode==2)
SFG_enroll();
lcdcleartxt();
if(confirmcode==0)
{
ida1=pageid/100;
ida2=pageid/10%10;
ida3=pageid%10;
lcddisplay_string(1,1,"指纹采集成功");
lcddisplay_string(2,1,"编号为:");
lcdwritecommand(0x8d);
lcdwrite(0x30+ida1);
lcdwrite(0x30+ida2);
lcdwrite(0x30+ida3);
}
else if(confirmcode!=0)
{
lcddisplay_string(1,1,"指纹采集失败");
lcddisplay_string(2,1,"请重新操作");
}
lcddisplay_string(3,0,"按任意键继续");
while(keyscan()==0);
}
lcdcleartxt();
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
}
void deletefingerprint()
{
unsigned char i,j=0;
lcdcleartxt();
lcddisplay_string(1,0,"输入想删除的指纹号");
for(i=1;i<5;i++)dz[i]=0;
key=keyscan();
while(key!=confirm)
{
key=keyscan();
keyboard(key);
delayms(30);
if(key==0)K=10;
if((K>=0)&&(K<=9))
{
dz[j]=K;
if(j<3)
{
lcdwritecommand(0x88+j);
lcdwrite(0x30+dz[j]);
}
++j;
if(j==4)
j=3;
}
if(K==34)//照常删除键
{
if(j==0)
{
lcdwritecommand(0x88);
lcdwrite(0x20);
}
else
{
--j;
lcdwritecommand(0x88+j);
lcdwrite(0x20);
}
}
}
if(j>=2)pageid=dz[2]+dz[1]*10+dz[0]*100;
if(j==1)pageid=dz[1]+dz[0]*10;
if(j==0)pageid=dz[0];
SFG_deletchar(pageid);
if(confirmcode==0)
{
lcdcleartxt();
lcddisplay_string(1,1,"成功删除指纹号。");
}
else
{
lcdcleartxt();
lcddisplay_string(1,2,"删除指纹号失败。");
}
lcddisplay_string(2,0,"按任意键继续");
while(keyscan()==0);
lcdcleartxt();
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
}
/*第二部分-第五模块:修改密码*/
void changepass()
{
unsigned char i,j=0,password1[6],password2[6];
unsigned char k,temp;
lcdcleartxt();
lcddisplay_string(1,1,"请输入新密码");
for(i=0;i<6;i++)password1[i]=0;
key=keyscan();
while(key!=confirm)
{
key=keyscan();
keyboard(key);
delayms(30);
if(key==0)K=10;
if((K>=0)&&(K<=9))
{
password1[j]=K;
if(j<6)
{
lcdwritecommand(0x89+j);
lcdwrite(0x0f);
}
++j;
if(j==7);
j=6;
}
if(K==34)
{
if(j==0)
{
lcdwritecommand(0x89);
lcdwrite(0x0f);
}
else
{
--j;
lcdwritecommand(0x89+j);
lcdwrite(0x20);
}
}
}
lcdcleartxt();
lcdcleartxt();
j=0;
lcddisplay_string(1,0,"请再次输入新密码");
for(i=0;i<6;i++)password2[i]=0;
key=keyscan();
while(key!=confirm)
{
key=keyscan();
keyboard(key);
delayms(30);
if(key==0)K=10;
if((K>=0)&&(K<=9))
{
password2[j]=k;
if(j<6)
{
lcdwritecommand(0x89+j);
lcdwrite(0x0f);
}
++j;
if(j==7);
j=6;
}
if(K==34)//按了删除键
{
if(j==0)
{
lcdwritecommand(0x89);
lcdwrite(0x20);
}
else
{
--j;
lcdwritecommand(0x89+j);
lcdwrite(0x20);
}
}
}
lcdcleartxt();
if((password1[0]==password2[0])&&(password1[1]==password2[1])&&(password1[2]==password2[2])&&(password1[3]==password2[3])&&(password1[4]==password2[4])&&(password1[5]==password2[5]))
{
for(i=1;i<6;i++)
passwordid[i]=password1[i];
for(i=0;i<6;i++)
{
userpassword[i]=password+0x30;
}
temp=1;
delayms(5);
for(k=0;k<6;k++)
{
writeinrom(temp,userpassword[k]);
delayms(10);
temp++;
}
lcddisplay_string(0,1,"密码修改成功");
lcddisplay_string(3,0,"按任意键继续");
errorcount=0;
while(keyscan()==0);
}
else
{
lcddisplay_string(0,0,"密码修改失败");
lcddisplay_string(1,0,"两次输入的密码不");
lcddisplay_string(2,0,"一致,请重新操作");
lcddisplay_string(3,0,"按任意键继续");
while(keyscan()==0);
}
lcdcleartxt();
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
}
/*第二部分-第六模块:后台管理员设置*/
void administrator()
{
unsigned char i,j=0,x=1;
unsigned char flag2;
lcdcleartxt();
lcddisplay_string(1,1,"请输入密码:");
for(i=0;i<6;i++)password[i]=0;
key=keyscan();
while(key!=confirm)
{
key=keyscan();
keyboard(key);
delayms(30);
if(key==0)K=10;
if((K>=0)&&(K<=9))
{
password[j]=K;
if(j<6)
{
lcdwritecommand(0x89+j);//同样的第三行显示密码
lcdwrite(0x0f);
}
++j;
if(j==7)
j=6;
}
if(K==34)
{
if(j==0)
{
lcdwritecommand(0x89);//同样的第三行显示密码
lcdwrite(0x20);
}
else
{
--j;
lcdwritecommand(0x89+j);
lcdwrite(0x20);
}
}
}
lcdcleartxt();
for(i=0;i<6;i++)
{
userpassword[i]=password[i]+0x30;
}
if(j==6)
{
if(password[0]==1&&password[1]==2&&password[2]==3&&password[3]==4&&password[4]==5&&password[5]==6)//设置后台管理密码
flag2=1;
else
flag2=0;
}
if(flag2==1)
{
flag2=0;
for(i=0;i<6;i++)password[i]=0;
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
while(i!=quit)
{
i=keyscan();
keyboard(i);
switch(K)
{
case 1:use_hand();K=8;break;
case 2:changepass();break;
default:break;
}
}
}
else
{
lcddisplay_string(1,2,"密码错误");
lcddisplay_string(2,0,"请重新操作");
lcddisplay_string(3,0,"按任意键继续");
while(keyscan()==0);
lcddisplay_string(0,0,"数字1:增加指纹");
lcddisplay_string(1,0,"数字2:删去指纹");
lcddisplay_string(2,0,"数字3:手动开锁");
lcddisplay_string(3,0,"数字4:修改密码");
}
key=0;
}
/*第二部分-第七模块:界面的设计与逻辑*/
void begin()
{
if(key!=0x81) //没按管理员键
{
lcddisplay_string(0,2,"欢迎使用");
lcddisplay_string(1,1,"密码锁");
lcddisplay_string(2,1,"请按c键开锁");
lcddisplay_string(3,1,"请输入指纹开锁");
}
key=keyscan();
if(k2==1)
{
lcdcleartxt();
use_fingerprint();
lcdcleartxt();
}
if(key==0x81)//后台管理员模式
{
lcdcleartxt();
administrator();
lcdcleartxt();
}
if(key==0x84&&errorcount<3)//选择用密码开锁
{
lcdcleartxt();
use_password();
lcdcleartxt();
}
}
void main()
{
UsartConfiguration();
at24c02_init();
lcdinit();
lcdcleartxt();
while(1)
{
begin();
delayms(100);
}
}