
功能键
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键盘实现密码的输入功能,当密码输入正确之后,锁就打开,如果输入的密码、华为手机如何锁定后台应用等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)