您的当前位置:首页正文

基于51单片机的简易电子密码锁

2022-09-24 来源:榕意旅游网


前言

随着电子技术的发展,具有防盗报警等功能的电子密码锁代替密码量少、安全性差的机械式密码锁已是必然趋势。电子密码锁与普通机械锁相比,具有许多独特的优点:保密性好,防盗性强,可以不用钥匙,记住密码即可开锁等。目前使用的电子密码锁大部分是基于单片机技术,以单片机为主要器件,其编码器与解码器的生成为软件方式。

下面就是现在主流电子密码锁:目前常见的遥控式电子防盗锁主要有光遥控和无线电遥控两类。键盘式电子密码锁从目前的技术水平和市场认可程度看,使用最为广泛的是键盘式电子密码锁,该产品主要应用于保险箱、保险柜和金库,还有一部分应用于保管箱和运钞车。卡式电子防盗锁使用各种“卡”作为钥匙的电子防盗锁是当前最为活跃的产品,无论卡的种类如何多种多样,按照输入卡的操作方式,都可分为接触式卡和非接 触式卡两大类。生物特征防盗锁人的某些与生俱来的个性特征(如手、眼睛、声音的 特征)几乎不可重复,作为“钥匙”就是唯一的(除非被逼迫或伤害)。因此,利用生物特征做密码的电子防盗锁,也特别适合金融业注重“验明正身”的行业特点。

人们生活水平的提高和安全意识的加强,对安全的要求也就越来越高。锁自 古以来就是把守护门的铁将军,人们对它要求甚高,既要安全可靠的防盗,又要使用方便,这也是制锁者长期以来研制的主题。随着电子技术的发展,各类电子产品应运而生,电子密码锁就是其中之一。据有关资料介绍,电子密码锁的研究从20世纪30年代就开始了,在一些特殊场所早就有所应用。这种锁是通过键盘输入一组密码完成开锁过程。研究这种锁的初衷,就是为提高锁的安全性。由于电子锁的密钥量(密码 量)极大,可以与机械锁配合使用,并且可以避免因钥匙被仿制而留下安全隐患。电子锁只需记住一组密码,无需携带金属钥匙,免除了人们携带金属钥匙的烦恼,而被越来越多的人所欣赏。电子锁的种类繁多,例如数码锁,指纹锁,磁卡锁,IC 卡锁,生物锁等。但较实用的还是按键式电子密码锁。20世纪80年代后,随着电子锁专用集成电路的出现,电子锁的体积缩小,可靠性提高,成本较高,是适合使用在安全性要求较高的场合,且需要有电源提供能量,使用还局限在一定范围,难以普及,所以对它的研究一直没有明显进展。 目前,在西方发达国家,电子密码锁技术相对先进,种类齐全,电子密码锁已被 广泛应用于智能门禁系统中,通过多种更加安全,更加可靠的技术实现大门的管理。

在我国电子锁整体水平尚处于国际上70年代左右,电子密码锁的成本还很高,市场上仍以按键电子锁为主,按键式和卡片钥匙式电子锁已引进国际先进水平,现国内有几个厂生产供应市场。但国内自行研制开发的电子锁,其市场结构尚未形成,应用还不广泛。国内的不少企业也引进了世界上先进的技术,发展前景非常可观。希望通过不断的努力,使电子密码锁在我国也能得到广泛应用。

一、 作品功能:

1、设置6位密码,密码通过键盘输入,若密码正确,则将锁打开。 2、密码可以由用户自己修改设定(只支持6位密码),锁打开后才能修改密

码。修改密码之前必须再次输入密码,在输入新密码时候需要二次确认,以防止误操作。

3、报警、锁定键盘功能。密码输入错误显示器会出现错误提示,若密码输

入错误次数超过3次,蜂鸣器报警并且锁定键盘。 4、AT24C02保存密码,支持复位保存,掉电保存功能。 二、按键说明

按键定义图

如图示:采用4X4键盘输入,键盘对应名称如下:

1 2 3 A 4 5 6 B 7 8 9 C * 0 # D

其中, 【0—9】为数字键,用于输入相应的密码, 【*】号键为取消当前操作 【#】号键为确认 【D】键为修改密码 其它键无功能及定义 三、操作说明:

密码锁初始密码为:000000.

1、开锁:插上电源后,程序自动调入初始密码,此时依次输 入:000000,然后按【#】(确认)键,此时锁会打开,可以看到显示open,密码锁打开。 2、退出并关锁:按下【*】(取消)键,此时锁关闭,所有输入清除。 3、修改密码:在开锁状态下,再次输入正确的密码并按下【#】(确认)键,此

时听到两声提示,输入新的六位密码并按【D】(重设)键,再重复输入一次新密码并按【D】,会听到两声提示音,表示重设密码成功,内部保存新密码并存储到AT24C02。(如两次输入的新密码不一样,则重设密码失败)。 4、报警并锁定键盘:当输入密码错误后,报警并锁定键盘3秒,如3秒内又有按键,3秒再启动。

5、当重置新密码时,新密码会保存于AT24C02存储器里。

四、框图及流程图 1、系统结构框图

键盘输入模块 AT89S52 显示模块 复位电路 密码存储模块 报警电路 开锁电路

2、主程序设计流程图

初始化

开锁 修改

输入旧密码 密码正确 N Y N N 开锁 出错报警 原密码相同 Y

设新密码

返回

3、键功能程序流程图。

N Y N 键值=设置? 键值=0~9? 键功能程序 Y 密码输入程序 N Y 开锁程序 键值=开锁? Y 设置程序 键值=确认? 确认程序

N 返回

4、开锁程序流程图

输入密码 按开锁键 LCD初始化 开锁

Y 返回 开锁成功 N 输入密码正确? 报警程序 确认程序

5.电子密码锁原理图

程序(c语言)

#include #include #define LCM_Data P0

#define uchar unsigned char #define uint unsigned int

#define w 6 //定义密码位数 sbit lcd1602_rs=P2^5; sbit lcd1602_rw=P2^6; sbit lcd1602_en=P2^7;

sbit Scl=P3^4; //24C02串行时钟 sbit Sda=P3^5; //24C02串行数据 sbit ALAM = P2^1; //报警 sbit KEY = P2^0; //开锁

sbit open_led=P2^2; //开锁指示灯 bit operation=0; //操作标志位 bit pass=0; //密码正确标志

bit ReInputEn=0; //重置输入充许标志 bit s3_keydown=0; //3秒按键标志位 bit key_disable=0; //锁定键盘标志

unsigned char countt0,second; //t0中断计数器,秒计数器 void Delay5Ms(void);

unsigned char code a[]={0xFE,0xFD,0xFB,0xF7}; //控盘扫描控制表 unsigned char code start_line[] = {\"password: \

unsigned char code name[] = {\"===Coded Lock===\显示名称 unsigned char code Correct[] = {\" correct \//输入正确

unsigned char code Error[] = {\" error \//输入错误unsigned char code codepass[] = {\" pass \

unsigned char code LockOpen[] = {\" open \ //OPEN unsigned char code SetNew[] = {\"SetNewWordEnable\

unsigned char code Input[] = {\"input: \ //INPUT unsigned char code ResetOK[] = {\"ResetPasswordOK \unsigned char code initword[] = {\"Init password...\unsigned char code Er_try[] = {\"error,try again!\unsigned char code again[] = {\"input again \

unsigned char InputData[6]; //输入密码暂存区unsigned char CurrentPassword[6]={1,3,1,4,2,0}; //当前密码值 unsigned char TempPassword[6];

unsigned char N=0; //密码输入位数记数 unsigned char ErrorCont; //错误次数计数

unsigned char CorrectCont; //正确输入计数 unsigned char ReInputCont; //重新输入计数 unsigned char code initpassword[6]={0,0,0,0,0,0};

//=====================5ms延时============================== void Delay5Ms(void) {

unsigned int TempCyc = 5552; while(TempCyc--); }

//===================400ms延时============================== void Delay400Ms(void) {

unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) {

TempCycB=7269; while(TempCycB--); } }

//================================24C02====================================== void mDelay(uint t) //延时 {

uchar i; while(t--) {

for(i=0;i<125;i++) {;} } }

void Nop(void) //空操作 {

_nop_(); _nop_(); _nop_(); _nop_(); }

/*起始条件*/ void Start(void) {

Sda=1; Scl=1; Nop(); Sda=0;

Nop(); }

/*停止条件*/ void Stop(void) {

Sda=0; Scl=1; Nop(); Sda=1; Nop(); }

/*应答位*/ void Ack(void) {

Sda=0; Nop(); Scl=1; Nop(); Scl=0; }

/*反向应答位*/ void NoAck(void) {

Sda=1; Nop(); Scl=1; Nop(); Scl=0; }

/*发送数据子程序,Data为要求发送的数据*/ void Send(uchar Data) {

uchar BitCounter=8; uchar temp; do {

temp=Data; Scl=0; Nop();

if((temp&0x80)==0x80) Sda=1; else

Sda=0; Scl=1;

temp=Data<<1; Data=temp; BitCounter--; }

while(BitCounter); Scl=0; }

/*读一字节的数据,并返回该字节值*/ uchar Read(void) {

uchar temp=0; uchar temp1=0;

uchar BitCounter=8; Sda=1; do{ Scl=0; Nop(); Scl=1; Nop(); if(Sda)

temp=temp|0x01; else

temp=temp&0xfe; if(BitCounter-1) {

temp1=temp<<1; temp=temp1; }

BitCounter--; }

while(BitCounter); return(temp); }

void WrToROM(uchar Data[],uchar Address,uchar Num) {

uchar i;

uchar *PData; PData=Data;

for(i=0;iStart(); Send(0xa0);

Ack();

Send(Address+i); Ack();

Send(*(PData+i)); Ack(); Stop(); mDelay(20); } }

void RdFromROM(uchar Data[],uchar Address,uchar Num) {

uchar i;

uchar *PData; PData=Data;

for(i=0;iStart(); Send(0xa0); Ack();

Send(Address+i); Ack(); Start(); Send(0xa1); Ack();

*(PData+i)=Read(); Scl=0; NoAck(); Stop(); } }

//=======================================LCD1602=============================//#define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)

#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40) //----------------延时函数,后面经常调用---------------------- void delay(uint xms)//延时函数,有参函数 {

uint x,y;

for(x=xms;x>0;x--) for(y=110;y>0;y--); }

//--------------------------写指令--------------------------- write_1602com(uchar com)//****液晶写入指令函数**** {

lcd1602_rs=0;//数据/指令选择置为指令 lcd1602_rw=0; //读写选择置为写 P0=com;//送入数据 delay(1);

lcd1602_en=1;//拉高使能端,为制造有效的下降沿做准备 delay(1);

lcd1602_en=0;//en由高变低,产生下降沿,液晶执行命令 }

//-------------------------写数据----------------------------- write_1602dat(uchar dat)//***液晶写入数据函数**** {

lcd1602_rs=1;//数据/指令选择置为数据 lcd1602_rw=0; //读写选择置为写 P0=dat;//送入数据 delay(1);

lcd1602_en=1; //en置高电平,为制造下降沿做准备 delay(1);

lcd1602_en=0; //en由高变低,产生下降沿,液晶执行命令 }

//-------------------------初始化------------------------- void lcd_init(void) {

write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据 write_1602com(0x0c);//开显示不显示光标

write_1602com(0x06);//整屏不移动,光标自动右移 write_1602com(0x01);//清显示 }

//==============将按键值编码为数值========================= unsigned char coding(unsigned char m) {

unsigned char k;

switch(m) {

case (0x18): k=1;break; case (0x28): k=2;break; case (0x48): k=3;break; case (0x88): k='A';break; case (0x14): k=4;break; case (0x24): k=5;break; case (0x44): k=6;break; case (0x84): k='B';break; case (0x12): k=7;break;

case (0x22): k=8;break; case (0x42): k=9;break; case (0x82): k='C';break; case (0x11): k='*';break; case (0x21): k=0;break; case (0x41): k='#';break; case (0x81): k='D';break; }

return(k); }

//=====================按键检测并返回按键值=============================== unsigned char keynum(void) {

unsigned char row,col,i; P1=0xf0;

if((P1&0xf0)!=0xf0) {

Delay5Ms(); Delay5Ms();

if((P1&0xf0)!=0xf0) {

row=P1^0xf0; //确定行线 i=0;

P1=a[i]; //精确定位 while(i<4) {

if((P1&0xf0)!=0xf0) {

col=~(P1&0xff); //确定列线

break; //已定位后提前退出 } else {

i++; P1=a[i]; } } } else {

return 0; }

while((P1&0xf0)!=0xf0);

return (row|col); //行线与列线组合后返回 }

else return 0; //无键按下时返回0 }

//=======================一声提示音,表示有效输入======================== void OneAlam(void) {

ALAM=0; Delay5Ms(); ALAM=1; }

//========================二声提示音,表示操作成功======================== void TwoAlam(void) {

ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; }

//========================三声提示音,表示错误======================== void ThreeAlam(void) {

ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0; Delay5Ms(); ALAM=1; }

//=====================显示输入的N个数字,用H代替以便隐藏============================ void DisplayOne(void) {

// DisplayOneChar(9+N,1,'*');

write_1602com(yi+5+N); write_1602dat('*'); }

//=======================显示提示输入========================= void DisplayChar(void) {

unsigned char i; if(pass==1) {

//DisplayListChar(0,1,LockOpen); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(LockOpen[i]); } } else {

if(N==0) {

//DisplayListChar(0,1,Error); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Error[i]); } } else {

//DisplayListChar(0,1,start_line); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(start_line[i]); } } } }

void DisplayInput(void) {

unsigned char i; if(CorrectCont==1) {

//DisplayListChar(0,0,Input);

write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Input[i]); } } }

//========================重置密码==================================================

//==================================================================================

void ResetPassword(void) {

unsigned char i; unsigned char j; if(pass==0) {

pass=0;

DisplayChar(); ThreeAlam(); } else {

if(ReInputEn==1) {

if(N==6) {

ReInputCont++; if(ReInputCont==2) {

for(i=0;i<6;) {

if(TempPassword[i]==InputData[i]) //将两次输入的新密码作对比

i++; else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); //错误提示

pass=0;

ReInputEn=0; //关闭重置功能, ReInputCont=0; DisplayChar(); break; } }

if(i==6) {

//DisplayListChar(0,1,ResetOK); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(ResetOK[j]); }

TwoAlam(); //操作成功提示

WrToROM(TempPassword,0,6); //将新密码写入24C02存储 ReInputEn=0; }

ReInputCont=0; CorrectCont=0; } else {

OneAlam();

//DisplayListChar(0, 1, again); //显示再次输入一次 write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(again[j]); } for(i=0;i<6;i++) {

TempPassword[i]=InputData[i]; //将第一次输入的数据暂存起来 } }

N=0; //输入数据位数计数器清零 } } }

}

//=======================输入密码错误超过三过,报警并锁死键盘====================== void Alam_KeyUnable(void) {

P1=0x00; {

ALAM=~ALAM; Delay5Ms(); } }

//=======================取消所有操作============================================ void Cancel(void) {

unsigned char i; unsigned char j;

//DisplayListChar(0, 1, start_line); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(start_line[j]); }

TwoAlam(); //提示音 for(i=0;i<6;i++) {

InputData[i]=0; }

KEY=1; //关闭锁 ALAM=1; //报警关

operation=0; //操作标志位清零 pass=0; //密码正确标志清零 ReInputEn=0; //重置输入充许标志清零 ErrorCont=0; //密码错误输入次数清零 CorrectCont=0; //密码正确输入次数清零 ReInputCont=0; //重置密码输入次数清零 open_led=1; s3_keydown=0; key_disable=0;

N=0; //输入位数计数器清零 }

//==========================确认键,并通过相应标志位执行相应功能

=============================== void Ensure(void) {

unsigned char i,j;

RdFromROM(CurrentPassword,0,6); //从24C02里读出存储密码 if(N==6) {

if(ReInputEn==0) //重置密码功能未开启 {

for(i=0;i<6;)

{

if(CurrentPassword[i]==InputData[i]) {

i++; } else

{ ErrorCont++;

if(ErrorCont==3) //错误输入计数达三次时,报警并锁定键盘

{

write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Error[i]); } do

Alam_KeyUnable(); while(1); } else {

TR0=1; //开启定时 key_disable=1; //锁定键盘 pass=0; break; } } }

if(i==6) {

CorrectCont++;

if(CorrectCont==1) //正确输入计数,当只有一次正确输

入时,开锁,

{

//DisplayListChar(0,1,LockOpen); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(LockOpen[j]); }

TwoAlam(); //操作成功提示音

KEY=0; //开锁

pass=1; //置正确标志位

TR0=1; //开启定时 open_led=0; //开锁指示灯亮

for(j=0;j<6;j++) //将输入清除

{

InputData[i]=0; } }

else //当两次正确输入时,开启重置密码功能 {

//DisplayListChar(0,1,SetNew); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(SetNew[j]); }

TwoAlam(); //操作成功提示

ReInputEn=1; //允许重置密码输入

CorrectCont=0; //正确计数器清零

} }

else //=========================当第一次使用或忘记密码时可以用131420对其密码初始化============ {

if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==

4)&&(InputData[4]==2)&&(InputData[5]==0)) {

WrToROM(initpassword,0,6); 入24C02存储

//DisplayListChar(0,1,initword); 码

write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(initword[j]); }

TwoAlam(); Delay400Ms(); TwoAlam(); N=0; } else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); 提示音

pass=0; } } }

else 能时,而按下开锁键, {

//DisplayListChar(0,1,Er_try); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Er_try[j]); }

ThreeAlam(); } }

//强制将初始密码写

//显示初始化密

//错误

//当已经开启重置密码功

else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); //错误提示音 pass=0; }

N=0; //将输入数据计数器清零,为下一次输入作准备

operation=1; }

//==============================主函数=============================== void main(void) {

unsigned char KEY,NUM; unsigned char i,j; P1=0xFF; TMOD=0x11; TL0=0xB0; TH0=0x3C; EA=1; ET0=1; TR0=0;

Delay400Ms(); //启动等待,等LCM讲入工作状态 lcd_init(); //LCD初始化

write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示 for(i=0;i<16;i++) {

write_1602dat(name[i]);//向液晶屏写日历显示的固定符号部分 }

write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示 for(i=0;i<16;i++) {

write_1602dat(start_line[i]);//写显示时间固定符号,两个冒号 }

write_1602com(er+9); //设置光标位置 write_1602com(0x0f); //设置光标为闪烁 Delay5Ms(); //延时片刻(可不要)

N=0; 入位数

while(1) {

if(key_disable==1) Alam_KeyUnable(); else

ALAM=1; //关报警

KEY=keynum(); if(KEY!=0) {

if(key_disable==1) {

second=0; } else {

NUM=coding(KEY); {

switch(NUM) {

case ('A'): ; case ('B'): ; case ('C'): ; case ('D'): ResetPassword(); 设置密码

case ('*'): Cancel(); 当前输入

case ('#'): Ensure(); 键,

default: {

//DisplayListChar(0,1,Input); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Input[i]); }

operation=0;

if(N<6) 入的密码少于6位时,接受输入并保存,大于6位时则无效。 {

//初始化数据输

break; break; break;

break; //重新break; //取消break; //确认

//当输

OneAlam(); 提示音

//DisplayOneChar(6+N,1,'*'); for(j=0;j<=N;j++) {

write_1602com(er+6+j); write_1602dat('*'); //按键

}

InputData[N]=NUM; N++; }

else 数据位数大于6后,忽略输入 {

N=6; break; } } } } } } } }

//*********************************中断************************************** void time0_int(void) interrupt 1 {

TL0=0xB0; TH0=0x3C; //TR0=1; countt0++;

if(countt0==20) {

countt0=0; second++; if(pass==1) {

if(second==1) {

open_led=1; //关指示灯 TR0=0; //关定时器 TL0=0xB0;

服务 //输入

函数

TH0=0x3C; second=0; } } else {

} } }

if(second==3) {

TR0=0; second=0;

key_disable=0; s3_keydown=0; TL0=0xB0; TH0=0x3C; } else

TR0=1;

结论,致谢,参考文献,原理图放在程序前

毕业设计是学生即将完成学业的最后一次作业,它既是对所学知识的全面总结和综合应用,又是今后走向社会的实际操作应用铸就了一个良好开端,毕业设计是我对所学知识理论的检验与总结,此次毕业设计是一次非常难得的理论与实际相结合的机会,通过这次比较难完整的毕业设计,我摆脱了单纯的理论知识学习状态,和实际设计的结合锻炼了我的综合运用所学的专业基础知识,同时也提高我查阅文献资料、设计手册、设计规范以及电脑制图等其它专业能力水平,而且通过对整体的掌控,对局部的取舍,以及对细节的斟酌处理,都使我的能力得到了锻炼,经验得到了丰富,并且使我的意志和耐力都得到了不同的提升,这是我们希望看到的也正是我们进行毕业设计的目的所在。

在此次试验中,我通过查阅大量的有关资料,与同学交流经验和自学,并向老师请教等方式完成的,

岁月如梭,三年的大学时光即将结束,这个实验和论文是在电子教研室105所有老师的知道与鼓励下完成的,老师们渊博的学识、严谨的治学态度、精益求精的工作态度和诲人不倦的高尚师德都深深感染和激励着我。在三年时光里,老师们不仅在学习上照顾我,同时也在思想和生活上给与我无微不至的关怀。在此,谨向105所有老师致以诚挚的感谢。

我还要感谢的是09电气数控的所有同学,是他们让我的大学生活变得更加丰富多彩,他们给予了我生活和学习上的帮助。

因篇幅问题不能全部显示,请点此查看更多更全内容