标题: 电子锁相关提问 [打印本页]
作者: 玄佑 时间: 2017-4-28 14:38
标题: 电子锁相关提问
这是网上找的一个电子锁程序,自己进行仿真了,但是输入密码环节不知道初始密码,也好像没法设定初始密码,有没有大神可以帮我看一下,是不是程序问题,还是我自己没搞懂?
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden=P1^2;
sbit lcdrs=P1^0;
sbit lcdrw=P1^1;
sbit p17=P1^7; //开门指示:指示灯和蜂鸣器
uchar table1[8]={'N','A','M','E',':'}; //定义数码管的第一行"name: "
uchar table2[8]={'C','O','D','E',':'}; //定义数码管的第二行"lode: "
uchar name[10]={'0','1','2','3'};
uchar cod[20]={'0','0','0','0','1','1','1','1','2','2','2','2','3','3','3','3'}; //定义四个用户,并设置对应的用户和密码,
//其中用户0定义为超级用户0,用户1、用户2和用户3为普通用户
uint in_name; //保存输入的用户名
uint error_num; //输入密码错误的次数
uchar in_code1[4]; //保存第一次输入的密码
uchar in_code2[4]; //保存第二次输入的密码
uchar code sup[11]={'S','U','P','E','R',' ','U','S','E','R','!'}; //输入用户为超级用户
uchar code nor[12]={'N','O','R','M','A','L',' ','U','S','E','R','!'}; //输入用户为普通用户
uchar code err[6]={'E','R','R','O','R','!'}; //输入用户名或密码错误
uchar wait[8]={'W','A','I','T','I','N','G','!'}; //等待
uchar aga[11]={'I','N','P','U','T',' ','A','G','A','I','N'}; //再次输入密码
uchar ame[9]={'A','M','E','N','D','I','N','G','!'}; //正在修改密码
uchar fun[6]={'a','b','c','d','e','f'}; //ABCDEF功能键
//====================延时函数======================//
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=110;b>0;b--);
}
//=================1602写指令===============//
void write_com(uchar com)
{
lcdrs=0;
P0=com;
delay(10);
lcden=1;
delay(10);
lcden=0;
}
//==============1602写数据================//
void write_data(uchar dat)
{
lcdrs=1;
P0=dat;
delay(10);
lcden=1;
delay(10);
lcden=0;
}
//===============1602在指定的位置显示一个字符=============//
void disp_char(uchar x,uchar y,uchar dat)
{
uint i;
uchar addr;
if(y==1)
addr=0x80+x;
else
addr=0xc0+x;
write_com(addr);
for(i=0;i<2;i++);
write_data(dat);
for(i=0;i<2;i++);
}
//==================1602数码管初始化函数==================//
void display()
{
lcden=0;
lcdrw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
//=============4*4键盘扫描函数=================//
uint keyscan()
{
uchar temp;
uint key=16; //key=16表示没有按下任何键
P2=0xfe; //第一行被置为低电平,开始扫描第一行
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(1);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case(0xee):
key=0;
break;
case(0xde):
key=1;
break;
case(0xbe):
key=2;
break;
case(0x7e):
key=3;
break;
}
while(temp!=0xf0) //等待按键释放
{
temp=P2;
temp=temp&0xf0;
}
}
}
///////////////////////////////////////////
P2=0xfd; //第二行被置为低电平,开始扫描第二行
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(1);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case(0xed):
key=4;
break;
case(0xdd):
key=5;
break;
case(0xbd):
key=6;
break;
case(0x7d):
key=7;
break;
}
while(temp!=0xf0) //等待按键释放
{
temp=P2;
temp=temp&0xf0;
}
}
}
////////////////////////////////////////
P2=0xfb; //第三行被置为低电平,开始扫描第三行
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(1);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case(0xeb):
key=8;
break;
case(0xdb):
key=9;
break;
case(0xbb):
key=10;
break;
case(0x7b):
key=11;
break;
}
while(temp!=0xf0) //等待按键释放
{
temp=P2;
temp=temp&0xf0;
}
}
}
//////////////////////////////////////////////
P2=0xf7; //第四行被置为低电平,开始扫描第四行
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(1);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case(0xe7):
key=12;
break;
case(0xd7):
key=13;
break;
case(0xb7):
key=14;
break;
case(0x77):
key=15;
break;
}
while(temp!=0xf0) //等待按键释放
{
temp=P2;
temp=temp&0xf0;
}
}
}
return(key);
}
/*/---------------B键的功能,删除用户--------------------//
void delete_user()
{
;
}
//--------------D键的功能,添加用户----------------------//
void add_user()
{
;
} */
//----------------E键的功能,修改密码-------------//
void amend_code()
{
uint i,j,k=16;
display();
for(i=0;i<5;i++)
disp_char(i,1,table1); //第一行显示NAME:及对应的用户名
disp_char(5,1,name[in_name]);
for(i=0;i<5;i++)
disp_char(i,2,table2); //第二行显示CODE:AMENDING!
for(i=0;i<9;i++)
disp_char(i+5,2,ame);
for(j=0;j<4;j++)
{k=keyscan();
while(k==16)
k=keyscan();
cod[in_name*4+i]=fun[k-10];
}
}
//================F键的功能,开门,蜂鸣器间断响================//
void open_door()
{
uint i,j;
for(i=0;i<6;i++)
for(j=0;j<10000;j++)
{
if((j/5000)%2==0)
p17=1;
else
p17=0;
}
p17=0;
}
//===================超级用户相关操作======================//
void super_user()
{
uint k=16;
uint flag=0;
while(flag==0)
{
k=keyscan();
while(!(k==10||k==11||k==13||k==14||k==15)) //当A、B、D、E、F均未被按下时,继续扫描
k=keyscan();
if(k==10) // 当A键被按下时,返回
flag=1;
if(k==11) // 当B键被按下时,删除用户
{
flag=1;
// delete_user();
}
if(k==13) // 当D键被按下时,添加用户
{
flag=1;
// add_user();
}
if(k==14) // 当E键被按下时,修改密码
{
flag=1;
amend_code();
}
if(k==15) // 当F键被按下时,开门
{
flag=1;
open_door();
}
}
delay(6000);
}
//===================普通用户相关操作:改密、开门========================//
void normal_user()
{
uint k=16;
uint flag=0;
while(flag==0)
{
k=keyscan();
while(!(k==14||k==15)) //当没有按下E、F键时,继续扫描
k=keyscan();
if(k==14); //对应于E键
{
flag=1; //普通用户完成一项操作
amend_code(); //修改当前用户的密码
}
if(k==15)
{
flag=1; //普通用户完成一项操作
open_door(); //F键的功能,开门
}
}
delay(6000);
}
//=================第二次输入密码函数====================//
void input_code2()
{
uint i,j,flag2=0;
uint k2=16;
error_num=0;
while(flag2==0&&error_num<3)
{
for(i=0;i<4;i++) //输入4位数密码,保存在in_code2中
{
k2=keyscan();
while(k2==16)
k2=keyscan();
in_code2=fun[k2-10];
display();
for(j=0;j<5;j++)
disp_char(j,1,table1[j]); //第一行显示NAME:及对应的用户名
disp_char(5,1,name[in_name]);
for(j=0;j<5;j++)
disp_char(j,2,table2[j]); //第二行先后显示CODE:*,CODE:**,CODE:***,CODE:****
for(j=0;j<i+1;j++)
disp_char(5+j,2,'*');
delay(10);
}
delay(10);
//------检验输入的密码是否与第一次输入的密码一致-------//
if(in_code2[0]==in_code1[0]&&in_code2[1]==in_code1[1]&&in_code2[2]==in_code1[2]&&in_code2[3]==in_code1[3])
{
flag2=1; //输入密码正确,退出while循环
p17=1; //指示灯亮,蜂鸣器响,表示密码正确
delay(400);
p17=0;
}
else
{
flag2=0; //输入密码错误重新输入
error_num++;
display();
for(j=0;j<5;j++) //第一行显示NAME:及对应的用户名
disp_char(j,1,table1[j]);
disp_char(5,1,name[in_name]);
for(j=0;j<5;j++) //第二行显示CODE:ERROR!2
disp_char(j,2,table2[j]);
for(j=0;j<6;j++)
disp_char(j+5,2,err[j]);
disp_char(11,2,'2');
delay(10);
}
}
}
//=================第一次输入密码函数====================//
void input_code1()
{
uint i,j,n,flag1=0,k1=16;
error_num=0;
while(flag1==0&&error_num<3)
{
for(i=0;i<4;i++) //输入4位数密码,保存在in_code1中
{
k1=16;
k1=keyscan();
while(k1==16)
k1=keyscan();
in_code1=fun[k1-10];
display();
for(j=0;j<5;j++)
disp_char(j,1,table1[j]); //第一行显示NAME:及对应的用户名
disp_char(5,1,name[in_name]);
for(j=0;j<5;j++)
disp_char(j,2,table2[j]); //第二行先后显示CODE:*,CODE:**,CODE:***,CODE:****
for(n=0;n<i+1;n++)
disp_char(5+n,2,'*');
delay(10);
}
delay(600);
//-------------检验输入的密码是否正确---------//
if(in_code1[0]==cod[in_name*4+0]&&in_code1[1]==cod[in_name*4+1]&&in_code1[2]==cod[in_name*4+2]&&in_code1[3]==cod[in_name*4+3])
{
flag1=1; //输入密码正确,退出wlile循环,等待第二次输入密码
display();
for(j=0;j<5;j++)
disp_char(j,1,table1[j]); //第一行显示NAME:及对应的用户名
disp_char(5,1,name[in_name]);
for(j=0;j<5;j++)
disp_char(j,2,table2[j]); //第二行显示CODE:INPUT AGAIN
for(j=0;j<11;j++)
disp_char(j+5,2,aga[j]); //INPUT AGAIN
delay(10);
p17=0; //指示灯亮,蜂鸣器响,表示密码正确
delay(400);
p17=1;
}
else
{
flag1=0; //输入密码错误重新输入
error_num++;
display();
for(j=0;j<5;j++) //第一行显示NAME:及对应的用户名
disp_char(j,1,table1[j]);
disp_char(5,1,name[in_name]);
for(j=0;j<5;j++) //第二行显示CODE:ERROR!1
disp_char(j,2,table2[j]);
for(j=0;j<6;j++)
disp_char(j+5,2,err[j]);
disp_char(11,2,'1');
delay(100);
}
}
}
//=================输入用户名函数===================//
void input_name()
{
uint j,flag0=0,error_num=0;
uint k0=16;
while(flag0==0)
{
k0=keyscan();
while(k0==16) //k0=16表示未输入用户名
k0=keyscan();
//-----------------------------//
if(k0>=0&&k0<4) //输入为用户0、用户1、用户2、用户3
{
flag0=1; //flag=1表示输入一个正确的用户
in_name=k0; //记下所输入的正确用户的序号
display();
for(j=0;j<5;j++) //第一行显示NAME:及输入的用户
disp_char(j,1,table1[j]);
disp_char(5,1,k0);
for(j=0;j<5;j++) //第二行显示CODE:
disp_char(j,2,table2[j]);
delay(10);
p17=0; //指示灯亮,蜂鸣器响,表示用户名正确
delay(400);
p17=1;
}
//-------------------------------//
if((k0>=4&&k0<=15)) //输入的用户错误
{
flag0=0;
error_num++;
display();
for(j=0;j<5;j++) //第一行显示NAME:ERROR!
disp_char(j,1,table1[j]);
disp_char(5,1,fun[k0-10]);
for(j=0;j<6;j++)
disp_char(j+7,1,err[j]);
for(j=0;j<5;j++) //第二行显示CODE:
disp_char(j,2,table2[j]);
delay(10);
}
}
}
void init()
{
uint m;
p17=0;
display(); //等待输入用户名
for(m=0;m<5;m++)
disp_char(m,1,table1[m]);
for(m=0;m<8;m++)
disp_char(m+7,1,wait[m]);
for(m=0;m<5;m++) //第二行显示CODE:
disp_char(m,2,table2[m]);
delay(10);
}
//====================主函数=====================//
void main()
{
uint m;
init();
while(1)
{
input_name(); //进入用户名输入函数
input_code1(); //用户名正确,接下来第一次输入密码
if(error_num<3)
{
input_code2(); //第一次输入密码正确,第二次输入密码
if(error_num<3)
{
if(in_name==0)
{
// display();
for(m=0;m<5;m++) //第一行显示NAME:及对应的用户名
disp_char(m,1,table1[m]);
disp_char(5,1,name[in_name]);
for(m=0;m<11;m++) //第二行显示输入用户为超级用户
disp_char(m,2,sup[m]);
delay(10);
super_user(); //进入超级用户相关操作
}
else
{
// display();
for(m=0;m<5;m++) //第一行显示NAME:及对应的用户名
disp_char(m,1,table1[m]);
disp_char(5,1,name[in_name]);
for(m=0;m<12;m++) //第二行显示输入用户为普通用户
disp_char(m,2,nor[m]);
delay(10);
normal_user(); //进入普通用户相关操作
}
}
}
delay(500);
}
}
作者: zl2168 时间: 2017-4-28 21:52
本帖最后由 zl2168 于 2017-4-29 11:03 编辑
网上乱七八糟的,大都有bug,看看我给你推荐的。
功能齐全的电子密码锁
⑴ 电路设计 …
⑵ 功能设计 …
⑶ 程序设计 …
⑷ Proteus仿真 …
先Proteus仿真一下,确认有效,验证上述功能。
电子密码锁1.rar
(1.13 MB, 下载次数: 12)
仿真电路和Hex文件能在清华出版社网站免费下载,程序源代码只能到书上看了。到图书馆借,或到新华书店翻阅,或到网上书店打折购买。
以上摘自张志良编著《80C51单片机实用教程》ISBN978-7-04-044532-9,高教社出版。书中电路和程序设计有详细说明,程序语句条条有注解。
欢迎咨询,zzlls@126.com
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |