基于单片机的电子密码锁设计

基于单片机的电子密码锁设计,第1张

功能键

S6---S15 数字键0-9

S16---更改密码 S17---更改密码完毕后确认

S18---重试密码、重新设定 S19---关闭密码锁

初始密码:000000 密码位数:6位

注意:掉电后,所设密码会丢失,重新上点时,密码恢复为原始的000000

与P1相连的8位发光LED点亮代表锁被打开;熄灭代表锁被锁上

程序功能: 本程序结合了24C02存储器的存储功能,可以掉电保存密码。

第一次运行时,若输入000000原始密码后无反应,可以试验着将主程序中前面的

一小段被注释线屏蔽的程序前的注释线删掉,然后重新编译下载(可以将密码还原为000000)。

此后,再将这小段程序屏蔽掉,再编译下载。方可正常使用。

1、开锁:

下载程序后,直接按六次S7(即代表数字1),8位LED亮,锁被打开,输入密码时,

六位数码管依次显示小横杠。

2、更改密码:

只有当开锁(LED亮)后,该功能方可使用。

首先按下更改密码键S16,然后设置相应密码,此时六位数码管会显示设置密码对应

的数字。最后设置完六位后,按下S17确认密码更改,此后新密码即生效。

3、重试密码:

当输入密码时,密码输错后按下键S18,可重新输入六位密码。

当设置密码时,设置中途想更改密码,也可按下此键重新设置。

4、关闭密码锁:

按下S19即可将打开的密码锁关闭。

推荐初级演示步骤:输入原始密码000000---按下更改密码按键S16---按0到9设置密码---按S17

确认密码更改---按S18关闭密码锁---输入新的密码打开密码锁

/

#include<reg52h>

#include <intrinsh>

#define uint unsigned int

#define uchar unsigned char

uchar old1,old2,old3,old4,old5,old6; //原始密码000000

uchar new1,new2,new3,new4,new5,new6; //每次MCU采集到的密码输入

uchar a=16,b=16,c=16,d=16,e=16,f=16; //送入数码管显示的变量

uchar wei,key,temp;

bit allow,genggai,ok,wanbi,retry,close; //各个状态位

sbit dula=P2^6;

sbit wela=P2^7;

sbit beep=P2^3;

sbit sda=P2^0; //IO口定义

sbit scl=P2^1;

unsigned char code table[]=

{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,

0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};

/IIC芯片24C02存储器驱动程序/

void nop()

{

_nop_();

_nop_();

}

/////////24C02读写驱动程序////////////////////

void delay1(unsigned int m)

{ unsigned int n;

for(n=0;n<m;n++);

}

void init() //24c02初始化子程序

{

scl=1;

nop();

sda=1;

nop();

}

void start() //启动I2C总线

{

sda=1;

nop();

scl=1;

nop();

sda=0;

nop();

scl=0;

nop();

}

void stop() //停止I2C总线

{

sda=0;

nop();

scl=1;

nop();

sda=1;

nop();

}

void writebyte(unsigned char j) //写一个字节

{

unsigned char i,temp;

temp=j;

for (i=0;i<8;i++)

{

temp=temp<<1;

scl=0;

nop();

sda=CY; //temp左移时,移出的值放入了CY中

nop();

scl=1; //待sda线上的数据稳定后,将scl拉高

nop();

}

scl=0;

nop();

sda=1;

nop();

}

unsigned char readbyte() //读一个字节

{

unsigned char i,j,k=0;

scl=0; nop(); sda=1;

for (i=0;i<8;i++)

{

nop(); scl=1; nop();

if(sda==1)

j=1;

else

j=0;

k=(k<<1)|j;

scl=0;

}

nop();

return(k);

}

void clock() //I2C总线时钟

{

unsigned char i=0;

scl=1;

nop();

while((sda==1)&&(i<255))

i++;

scl=0;

nop();

}

////////从24c02的地址address中读取一个字节数据/////

unsigned char read24c02(unsigned char address)

{

unsigned char i;

start();

writebyte(0xa0);

clock();

writebyte(address);

clock();

start();

writebyte(0xa1);

clock();

i=readbyte();

stop();

delay1(100);

return(i);

}

//////向24c02的address地址中写入一字节数据info/////

void write24c02(unsigned char address,unsigned char info)

{

start();

writebyte(0xa0);

clock();

writebyte(address);

clock();

writebyte(info);

clock();

stop();

delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。

}

/密码锁程序模块/

void delay(unsigned char i)

{

uchar j,k;

for(j=i;j>0;j--)

for(k=125;k>0;k--);

}

void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)

{

dula=0;

P0=table[a];

dula=1;

dula=0;

wela=0;

P0=0xfe;

wela=1;

wela=0;

delay(5);

P0=table[b];

dula=1;

dula=0;

P0=0xfd;

wela=1;

wela=0;

delay(5);

P0=table[c];

dula=1;

dula=0;

P0=0xfb;

wela=1;

wela=0;

delay(5);

P0=table[d];

dula=1;

dula=0;

P0=0xf7;

wela=1;

wela=0;

delay(5);

P0=table[e];

dula=1;

dula=0;

P0=0xef;

wela=1;

wela=0;

delay(5);

P0=table[f];

dula=1;

dula=0;

P0=0xdf;

wela=1;

wela=0;

delay(5);

}

void keyscan()

{

{

P3=0xfe;

temp=P3;

temp=temp&0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xee:

key=0;

wei++;

break;

case 0xde:

key=1;

wei++;

break;

case 0xbe:

key=2;

wei++;

break;

case 0x7e:

key=3;

wei++;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp&0xf0;

beep=0;

}

beep=1;

}

}

P3=0xfd;

temp=P3;

temp=temp&0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xed:

key=4;

wei++;

break;

case 0xdd:

key=5;

wei++;

break;

case 0xbd:

key=6;

wei++;

break;

case 0x7d:

key=7;

wei++;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp&0xf0;

beep=0;

}

beep=1;

}

}

P3=0xfb;

temp=P3;

temp=temp&0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xeb:

key=8;

wei++;

break;

case 0xdb:

key=9;

wei++;

break;

case 0xbb:

genggai=1;

wei=0;

break;

case 0x7b:

if(allow)

ok=1;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp&0xf0;

beep=0;

}

beep=1;

}

}

P3=0xf7;

temp=P3;

temp=temp&0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xe7:

retry=1;

break;

case 0xd7:

close=1;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp&0xf0;

beep=0;

}

beep=1;

}

}

}

}

void shumima() //对按键采集来的数据进行分配

{

if(!wanbi)

{

switch(wei)

{

case 1:new1=key;

if(!allow) a=17;

else a=key; break;

case 2:new2=key;

if(a==17) b=17;

else b=key; break;

case 3:new3=key;

if(a==17) c=17;

else c=key; break;

case 4:new4=key;

if(a==17) d=17;

else d=key; break;

case 5:new5=key;

if(a==17) e=17;

else e=key; break;

case 6:new6=key;

if(a==17) f=17;

else f=key;

wanbi=1; break;

}

}

}

void yanzheng() //验证密码是否正确

{

if(wanbi) //只有当六位密码均输入完毕后方进行验证

{

if((new1==old1)&(new2==old2)&(new3==old3)&(new4==old4)&(new5==old5)&(new6==old6))

allow=1; //当输入的密码正确,会得到allowe置一

}

}

void main()

{

init(); //初始化24C02

/下面的一小段程序的功能为格式化密码存储区。

当24c02中这些存储区由于其他程序的运行而导致

所存数据发生了变化,或者密码遗忘时,

可以删掉其前面的注释线,然后重新编译下载。

而将密码还原为000000后,请将下面的程序用

注释屏蔽掉,重新编译、下载,方可正常使用/

// write24c02(110,0x00);

// write24c02(111,0x00);//24c02的第110到115地址单元作为密码存储区

// write24c02(112,0x00);

// write24c02(113,0x00);

// write24c02(114,0x00);

// write24c02(115,0x00);

//

old1=read24c02(110);

old2=read24c02(111);

old3=read24c02(112);

old4=read24c02(113);

old5=read24c02(114);

old6=read24c02(115);

while(1)

{

keyscan();

shumima();

yanzheng();

if(allow) //验证完后,若allow为1,则开锁

{

P1=0x00;

if(!genggai)

wanbi=0;

}

if(genggai) //当S16更改密码键被按下,genggai会被置一

{

if(allow) //若已经把锁打开,才有更改密码的权限

{

while(!wanbi) //当新的六位密码没有设定完,则一直在这里循环

{

keyscan();

shumima();

if(retry|close) //而当探测到重试键S18或者关闭密码锁键S19被按下时,则跳出

{ wanbi=1;

break;

}

display(a,b,c,d,e,f);

}

}

}

if(ok) //更改密码时,当所有六位新密码均被按下时,可以按下此键,结束密码更改

{ //其他时间按下此键无效

ok=0; wei=0;

genggai=0;

old1=new1;old2=new2;old3=new3; //此时,旧的密码将被代替

old4=new4;old5=new5;old6=new6;

//新密码写入存储区。

write24c02(110,old1);

write24c02(111,old2);

write24c02(112,old3);

write24c02(113,old4);

write24c02(114,old5);

write24c02(115,old6);

a=16;b=16;c=16;d=16;e=16;f=16;

}

if(retry) //当重试按键S18被按下,retry会被置位

{

retry=0; wei=0;wanbi=0;

a=16;b=16;c=16;d=16;e=16;f=16;

new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;

}

if(close) //当关闭密码锁按键被按下,close会被置位

{

close=0;genggai=0;//所有变量均被清零。

wei=0; wanbi=0;

allow=0;

P1=0xff;

a=16;b=16;c=16;d=16;e=16;f=16;

new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;

}

display(a,b,c,d,e,f); //实时显示

}

}

对着代码自己做吧,,要是还做不出来,,那我就不说什么了,,

#include <reg52h>

#define uint unsigned int

#define uchar unsigned char

#define KEY P3 //键盘输入端口

#define No_key 20 //无按键时的返回值

#define lcddata P2 //1602的数据输入端口

sbit lcden= P1^2;

sbit lcdrs= P1^0;

sbit lcdrw= P1^1;

sbit light= P1^3;

sbit light1= P1^4;

uchar j ; //用来统计输入 个数的全局变量

uchar aa; //用来在定时器中计数的 全局变量

uchar code table[]= " Hello!";

uchar code table1[]=" OK! " ;

uchar code table2[]="Enter please:" ;

uchar code key_table[16] =

{

1,2,3,10,

4,5,6,11,

7,8,9,12,

0,13,14,15

};

uchar password[]={2,0,1,0,9,3} ; //设定初始密码

uchar save[6]; //保存输入的数据

uchar conflag ; //确认标志

uchar lockflag; //锁键盘标志

uchar startflag; //开始标志

void delay(uint z); //延时子函数

void wright_com(uchar com); //写指令函数

void wright_data(uchar date) ; //写数据函数

void init(); //初始化

void display_OK(); // 显示OK

void delete(); //删除输入的最后一个数

uchar keyscan() ; //带返回值的键盘扫描程序

void enter_code(uchar t); //输入密码函数,把输入的数据存入数组中并在屏幕上显示相应的东西,

void confirm(); //确认密码对不对,把输入的数据与密码逐一对比,完全一样刚正确,

void succeed_an(); //输入密码成功时的 响应,

void fail_an(); //输入密码 失败时 响应

void lockkey(); //锁键盘三秒

void alarm(); //发出警报声

void reset(); //复位函数

void display_enter(); //显示输入

void main(void)

{

uchar temp;

init();

while(1)

{

if(lockflag)

{

temp=keyscan(); // 锁键期间也要进行键盘扫描

if(temp!=No_key) //重新记时三秒

{

aa=0; //重新在定时器中计数

}

}

else

{

temp=keyscan(); //反复扫描输入,等待随时输入

if(temp!=No_key) //有按键按下才进行下面的 *** 作

{

if(temp==10)

{

reset();

startflag=1; //开始标志置位

}

if(startflag)

{

enter_code(temp); //每扫描一次键盘就要进行一次处理,保存输入的数值

if(temp==13) //按下确认键盘就要进行密码确认

{

confirm(); //进行确认判断

if(conflag) //密码确认为正确

{

succeed_an(); //密码正确,作出相应的反应

}

else

{

fail_an(); //密码错误,作相应反应

}

}

if(temp==14)

{

delete(); //作删除 *** 作

}

}

}

}

}

}

/ 显示enter/

void display_enter()

{

uchar num;

wright_com(0x80);

for(num=0;num<13;num++)

{

wright_data(table2[num]);

}

}

/ 显示OK/

void display_OK()

{

uchar num;

wright_com(0x80);

for(num=0;num<13;num++)

{

wright_data(table1[num]);

}

}

/ 删除最后一个/

void delete()

{

wright_com(0x80+0x40+j); //确定删除对象

wright_data(' '); //显示空格即为删除

save[--j]=0; //删除后数据清零

wright_com(0x80+0x40+j); //为下次输入数据时写好位置,必须是在最后一个后面

}

/ 对各种变量进行复位/

void reset()

{

uchar num;

display_enter();

wright_com(0x80+0x40); //擦除屏幕上的显示

for(num=0;num<6;num++)

{

save[num]=0; //对输入的数值进行清零

wright_data(' '); //显示的是空格

}

wright_com(0x80+0x40); //下次再输入时可以又从起始位置输入

lockflag=0; //各种变量要清零回起始状态

conflag=0;

j=0;

}

/ 输入密码正确进行响应/

void succeed_an()

{

light=0; //灯亮

display_OK(); //显示成功

delay(1000);

light=1; //灯灭

}

/ 输入密码错误进行响应/

void fail_an()

{

alarm();

lockkey();

}

/ 发出警报声/

void alarm() //这个以后再扩展它

{

}

/锁键盘三秒/

void lockkey()

{

lockflag=1;

}

/输入密码并在屏幕上显示星号/

void enter_code(uchar t)

{

if(t>=0&&t<10)

{

if(j==0)

{

wright_com(0x80+0x40) ; //第一输入时要先写入地址指令,否则无法显示

wright_data('') ;

}

else

{

wright_data('') ;//不是第一个输入则不用再写地址

}

save[j++]=t; //保存输入的数据

}

}

/校对密码以确定是不是正确的/

void confirm()

{

uchar k;

for(k=0;k<6;k++)

{

if(password[k]!=save[k]) //对数组中的内容进行逐一比较,一旦有数据不对马上退出循环

{

break;

}

}

if(k==6) //要是条件退出的话说明六个数全对密码

{

conflag=1; // 进行标志密码正确

}

}

/中断服务程序/

void timer0() interrupt 1

{

TH0=(65536-50000)/256;

TL0=(65536-50000)%256; //重装初值

if(lockflag)

{

aa++;

light1=0;

if(aa>=60) //三秒到了

{

aa=0; //清零可以方便下次再使用

light1=1; //关闭警报

lockflag=0; //标志清零解除键锁,方便下次使用

}

}

}

/初始化/

void init()

{

uchar num;

/定时器初始化/

TMOD=1;

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

ET0=1;

EA=1; //开启总中断

TR0=1;//把定时器关闭

/1602初始化/

lcdrw=0; //这个必须要置 零,否则无法正常显示

lcden=0;

wright_com(0x38) ; //初始化

wright_com(0x0c) ; //打开光标 0x0c不显示光标 0x0e光标不闪,0x0f光标闪

wright_com(0x01) ; //清显示

wright_com(0x80) ;

for(num=0;num<9;num++)

{

wright_data(table[num]);

delay(1);

}

}

/1602写入指令/

void wright_com(uchar com)

{

lcdrs=0;

lcddata=com;

delay(1);

lcden=1;

delay(1);

lcden=0;

}

/1602写入数据/

void wright_data(uchar date)

{

lcdrs=1;

lcddata=date;

delay(1);

lcden=1;

delay(1);

lcden=0;

}

/延时函数/

void delay(uint z)

{

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--) ;

}

/4x4矩阵键盘扫描函数/

uchar keyscan()

{

uchar temp,num=No_key; //num的初值要为无键盘按下时的返回值

/扫描第一行/

KEY=0xfe;

temp=KEY;

temp=temp&0xf0; //读出高四位

while(temp!=0xf0)

{

delay(5); //延时消抖

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0) //确认确实有按键按下

{

temp=KEY;

switch(temp) //根据这八个电平可以确定是哪个按键按下

{

case 0xee:num=1;

break;

case 0xde:num=2;

break;

case 0xbe:num=3;

break;

case 0x7e:num=10;

break;

}

while(temp!=0xf0) //等待松手

{

temp=KEY;

temp=temp&0xf0;

}

}

}

/扫描第二行/

KEY=0xfd;

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

delay(5);

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

temp=KEY;

switch(temp)

{

case 0xed:num=4;

break;

case 0xdd:num=5;

break;

case 0xbd:num=6;

break;

case 0x7d:num=11;

break;

}

while(temp!=0xf0)

{

temp=KEY;

temp=temp&0xf0;

}

}

}

/扫描第三行/

KEY=0xfb;

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

delay(5);

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

temp=KEY;

switch(temp)

{

case 0xeb:num=7;

break;

case 0xdb:num=8 ;

break;

case 0xbb:num=9;

break;

case 0x7b:num=12;

break;

}

while(temp!=0xf0)

{

temp=KEY;

temp=temp&0xf0;

}

}

}

/扫描第四行/

KEY=0xf7;

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

delay(5);

temp=KEY;

temp=temp&0xf0;

while(temp!=0xf0)

{

temp=KEY;

switch(temp)

{

case 0xe7:num=0;

break;

case 0xd7:num=13;

break;

case 0xb7:num=14;

break;

case 0x77:num=15;

break;

}

while(temp!=0xf0)

{

temp=KEY;

temp=temp&0xf0;

}

}

}

return num;

}

为了节约电量和网络流量,锁屏后部分应用程序会自动关闭。

如果您希望某些应用一直保持运行状态,可以将此应用设置成后台保护, *** 作方式如下:

Magic UI 20/201:进入手机管家>应用启动管理,找到对应的应用,关闭自动管理,在d出的三个选项中,将允许后台活动的开关开启;

EMUI 90/EMUI 901:手机管家>应用启动管理,找到对应的应用,关闭自动管理,在d出的三个选项中,将允许后台活动的开关开启;

EMUI 8X:进入 手机管家> 启动管理,找到对应的应用,关闭自动管理,在d出的三个选项中,将允许后台活动的开关开启。

EMUI 5X:进入手机管家界面,点击 剩余 xx%> 锁屏清理应用,关闭需要在后台运行应用程序的开关。

EMUI 4X:进入 手机管家界面,点击 剩余 xx%> 受保护应用,打开对应应用程序的开关。

EMUI 31: 手机管家> 省电管理,从屏幕下半部分开始上划屏幕,点击 受保护应用,打开对应应用程序的开关。

EMUI 30: 手机管家> 省电管理> 耗电详情> 锁屏后继续运行,打开对应应用程序的开关。

如果您希望清理后台后应用也保持在后台运行,建议您在后台中点击应用上方的锁图标,将应用锁定在后台即可。

说明:省电模式如果设置成超级省电,超级省电模式会自动启用相关策略来进行省电,您即使设置了受保护应用可能也会在锁屏后被关闭。

以上就是关于基于单片机的电子密码锁设计全部的内容,包括:基于单片机的电子密码锁设计、单片机电子密码锁设计,采用4×4键盘实现密码的输入功能,当密码输入正确之后,锁就打开,如果输入的密码、华为手机如何锁定后台应用等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/10117827.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存