本设计采用单片机为主控芯片,结合外围电路,组成电子密码锁,用户想要打开锁,必先通过提供的键盘输入正确的密码才能将锁打开,密码输入错误有提示,为了提高安全性,当密码输入错误三次将报警。密码可以有用户自己修改设定,锁打开后才能修改密码。修改密码之前必须再次输入就的密码,在输入新密码的时候要二次确认,以防止误操作。 当用户需要开锁时,先按键盘开锁键之后按键盘的数字键0-9输入密码。密码输完后按下确认键,如果密码输入正确则开锁,表示不正确显示密码错误重新输入密码,当三次密码错误则发出报警;锁用发光二极管表示,亮表示锁开,当用户需要修改密码时,先按下键盘设置键后输入原来的密码,只有当输入的原密码正确后才能设置新密码。新密码输入无误后按确认键使新密码将得到存储,密码修改成功.
液晶初始状态显示welcome 开锁显示ok 密码输入错误显示off 其他可以随意发挥
数字键0~9对应输入数字0~9,功能键A键是确定键,B键是取消键,C键是改密码键,D键位上锁键
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define NOP3() _nop_();_nop_();_nop_()
uchar time_50ms=0;
***it rs=P2^2;
***it rw=P2^1;
***it e=P2^0;
***it SCL=P2^5;
***it SDA=P2^6;
***it P35=P3^5;
***it P36=P3^6;
***it P37=P3^7;
uchar data kong[7]={'','','','','','',0};
uchar data mima[7]={'1','2','3','4','5','6',0};
uchar data mima0[7]={'','','','','','',0};
uchar data mima1[7]={'','','','','','',0};
uchar data mima2[7]={'','','','','','',0};
uchar data mima3[7]={'','','','','','',0};
uchar data table1[7]={'1','9','9','0','1','0',0};
uchar code table2[15]="Enter Password:";
uchar code table4[16]="Password Error!";
uchar code table5[14]="Old Password:";
uchar code table6[14]="New Password:";
uchar code table7[12]="Enter Again:";
uchar code table8[12]="Enter Error!";
uchar code table9[15]="Modify Success!";
uchar code table10[13]="Welcome back!";
//***********************************
//相关函数的声明
//***********************************
void delay1ms();
void delay(uchar n);
void write_1602com(uchar com);
void write_1602dat(uchar dat);
void initinal(void);
bit lcdbusy();
uchar key_scan();
void enter_password(void); //功能:显示输入密码画面
void password_error(void);//功能:显示输入密码错误后的画面
void ok(void);//功能:显示输入密码正确后的画面
void new_password(void);//功能:显示输入新密码的画面
void enter_again(void);//功能:显示再次输入新密码的画面
void enter_error(void);//功能:显示两次输入的密码不一样后的画面
void modify_success(void);//功能:显示更改成功后的画面
void welcome(void); //功能:显示欢迎画面
void wtite_1602com(uchar com);
void write_1602dat(uchar dat);
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
void delay(uchar n)
{ unsigned char i,x,y;
for(i=0;i
/*****************************************************
函数功能:延时1ms
***************************************************/
void delay1(uchar n){ unsigned char i,j;
for(i=0;i
/*****************************************************
函数功能:定时器子函数,调用该函数可以计时
***************************************************/
void time( ){ TMOD = 0x01; //定时器0,工作方式1
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256; //50ms中断一次
EA = 1;ET0 = 1;TR0 = 1;}
/*****************************************************
函数功能:定时函数,在一段时间内没有键按下则关闭显示器
***************************************************/
void time_1( ) interrupt 1{
TH0 = (65536-65536)/256;TL0 = (65536-65536)%256;time_50ms++;
if(time_50ms==20){time_1s++;time_50ms=0;}
if(time_1s==20){write_1602com(0x01);write_1602com(0x0c);
time_1s=0; while(1);}}
//***********************************
//功能:使蜂鸣器发音
//***********************************
void warn(){P37=1;NOP3();NOP3();NOP3();
P37=0;NOP3();NOP3();NOP3(); }
//***********************************
//函数名:bit lcdbusy()
//功能:检测忙标志
//***********************************
bit lcdbusy(){bit result; rs=0;rw=1;e=1;
delay(1);
result=(bit)(P0&0x80);e=0;
return result;}
//************************************************
//函数名:写命令函数
//功能:调用该函数可能定义1602液晶显示器的各种命令
//************************************************
void write_1602com(uchar com){
while(lcdbusy());
e=0; rw=0; rs=0;
P0=com; delay(1);
e=1; delay(1);e=0;}
//*************************************************
//函数名:写数据函数
//功能:调入该函数可以向1602液晶显示器输入数据
//*************************************************
void write_1602dat(uchar dat){
while(lcdbusy());e=0;rw=0;rs=1;
P0=dat;delay(1);e=1;delay(1);e=0;}
//**************************************************
//函数名:初始化函数
//功能:对1602液晶显示器进行初始化
//**************************************************
void initinal(void){
rs=0;e=0;
write_1602com(0x38); //数据总线为8位,显示2行,0=5×7点阵/每字符
write_1602com(0x0f); //显示功能开,有光标,光标不闪烁
write_1602com(0x06); //显示光标
write_1602com(0x01); //清屏
write_1602com(0x80);}
//*********************************************
//函数名:显示函数
//功能:显示输入密码
//*********************************************
void enter_password(void){ uchar j;
initinal();write_1602com(0x80);
for(j=0;j<15;j++){write_1602dat(table2[j]);delay(10);}
write_1602com(0xc0+0x0a);}
//********************************************
//函数名:显示函数
//功能:显示输入密码错误后的画面
//********************************************
void password_error(void){uchar j;
write_1602com(0x0c); //显示功能开,无光标
write_1602com(0x80); //显示位置第一行第一列
write_1602com(0x01);
for(j=0;j<15;j++){write_1602dat(table4[j]);delay(10);}}
//******************************************
//函数名:显示函数
//功能:显示输入旧密码的画面
//******************************************
void old_password(void){uchar j;
initinal();write_1602com(0x80);
for(j=0;j<14;j++){write_1602dat(table5[j]);delay(10);}
write_1602com(0xc0+0x0a);}
//******************************************
//函数名:显示函数
//功能:显示输入新密码的画面
//******************************************
void new_password(void){uchar j;initinal();
write_1602com(0x80);
for(j=0;j<14;j++){write_1602dat(table6[j]);delay(10);}
write_1602com(0xc0+0x0a);}
//******************************************
//函数名:显示函数
//功能:显示再次输入新密码的画面
//******************************************
void enter_again(void){uchar j;initinal();
write_1602com(0x80);
for(j=0;j<12;j++){write_1602dat(table7[j]);delay(10);}
write_1602com(0xc0+0x0a);}
//********************************************
//函数名:显示函数
//功能:显示两次输入的密码不一样后的画面
//********************************************
void enter_error(void){uchar j;
write_1602com(0x0c); //显示功能开,无光标
write_1602com(0x80); //显示位置第一行第一列
write_1602com(0x01);
for(j=0;j<12;j++){write_1602dat(table8[j]);delay(10);}}
//******************************************
//函数名:显示函数
//功能:显示更改成功之后的画面
//******************************************
void modify_success(void){uchar j;write_1602com(0x0c);
write_1602com(0x80);write_1602com(0x01);
for(j=0;j<15;j++){write_1602dat(table9[j]);delay(10);}}
//******************************************
//函数名:显示函数
//功能:显示欢迎画面
//******************************************
void welcome(void){
uchar j;
write_1602com(0x0c); //显示功能开,无光标
write_1602com(0x80); //显示位置第一行第4列
write_1602com(0x01);
write_1602com(0x80);
for(j=0;j<13;j++){write_1602dat(table10[j]);delay(10);}}
//**************************************************
//函数名:键盘识别函数
//功能:通过扫描对键盘进行识别
//**************************************************
uchar key_num(){uint temp,b;
while(1){P1=0xfe; //开始扫描第一行
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0){delay(1);temp=P1;b=temp;temp=temp&0xf0;
if(temp!=0xf0){
while(temp!=0xf0){temp=P1;temp=temp&0xf0;}
switch(b){case 0xee: return '4';break;
case 0xde: return '3';break;
case 0xbe: return '2';break;
case 0x7e: return '1';break;}}}
P1=0xfd; //扫描第二行
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0){delay(1);temp=P1;b=temp;temp=temp&0xf0;
if(temp!=0xf0){
while(temp!=0xf0){temp=P1;temp=temp&0xf0;}
switch(b){case 0xed: return '8';break;
case 0xdd: return '7';break;
case 0xbd: return '6';break;
case 0x7d: return '5';break;}}}
P1=0xfb; //扫描第三行
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0){delay(1);temp=P1;b=temp;temp=temp&0xf0;
if(temp!=0xf0){
while(temp!=0xf0){temp=P1;temp=temp&0xf0;}
switch(b){ case 0xeb: return 'b';break;
case 0xdb: return 'a';break;
case 0xbb: return '0';break;
case 0x7b: return '9';break;}}}}}
/****************************************
只扫描第四行,禁止数字键输入
****************************************/
uchar key_gn(){uint temp,b;
while(1){P1=0xf7; //扫描第四行
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0){delay(1);temp=P1;b=temp;temp=temp&0xf0;
if(temp!=0xf0){
while(temp!=0xf0){ temp=P1;temp=temp&0xf0;}
switch(b){case 0xe7: return 'f';break;
case 0xd7: return 'e';break;
case 0xb7: return 'd';break;
case 0x77: return 'c';break;}}} }}
/****************************************
密码函数:将输入的密码写放进数组
****************************************/
uchar enter(uchar password[]){uchar m=0,j,back=0;
for(m=0;;){j=key_num();time_50ms=0;time_1s=0;
if(j>='0'&&j<='9'&&m<6){write_1602com(0x06);password[m]=j; m++;
write_1602dat('*');}
if(j=='a'){password[m+1]='';return 1;} if(j=='b'){if(m>0){write_1602com(0x11);write_1602dat(0x20);
write_1602com(0x11);password[m]='';m--;}} }}
/******************************************
启动I2C总线函数
******************************************/
void Start(){ SCL=1;
SDA=1;NOP3();
SDA=0;NOP3();
SCL=0;}
/******************************************
I2C停止
******************************************/
void Stop(){ SDA=0;
SCL=1;NOP3();
SDA=1;NOP3();}
/******************************************
发送应答位函数
******************************************/
void CHECK_ACK(){ SDA=0;NOP3();
SCL=1;NOP3();
SCL=0;NOP3();
SDA=1;}
/******************************************
发送非应答位函数
******************************************/
void CHECK_NACK(){ SDA=1;NOP3();
SCL=1;NOP3();
SCL=0;NOP3();
SDA=0;}
/******************************************
I2C初始化
******************************************/
void Init_24cxx(){ SDA=1;NOP3();
SCL=1;NOP3();}
/******************************************
读I2C函数
******************************************/
uchar I2C_Read(){
uchar i,temp;temp=0;
SDA=1;SCL=0;
for(i=0;i<8;i++){
temp=temp<<1;SCL=1;NOP3();
if(SDA==1){temp=temp+1;}NOP3();
SCL=0; }
return temp;}
/******************************************
写I2C函数
******************************************/
void I2C_Write(uchar date1){
uchar i,temp;temp=date1;
SCL=0;
for(i=0;i<8;i++){
SDA=(bit)(temp&0x80);
SCL=1;NOP3();SCL=0;
temp=temp<<1;}NOP3();}
/******************************************
写相应地址的数据
******************************************/
void Write_add(uint address,uchar date1){
uchar addrh,addrl;
addrh=address>>8;
addrl=address%256;
EA=0;
Start();
I2C_Write(0xa0);//发送命令字+芯片编号+P0+W
CHECK_ACK();
I2C_Write(addrh);//发高位地址
CHECK_ACK();
I2C_Write(addrl);//发低位地址
CHECK_ACK();
I2C_Write(date1);//发送数据
CHECK_ACK();
Stop();//停止
EA=1;}
/******************************************
读相应地址的数据
******************************************/
uchar Read_add(uint address){
uchar addrh,addrl,temp;
addrh=address>>8;
addrl=address%256;
EA=0;
Start();
I2C_Write(0xa0);
CHECK_ACK();
I2C_Write(addrh);//发高位地址
CHECK_ACK();
I2C_Write(addrl);//发低位地址
CHECK_ACK();
Start();
I2C_Write(0xa1);
CHECK_ACK();
temp=I2C_Read();
CHECK_NACK();
Stop();
EA=1;
return temp;
}
/******************************************
写数据函数:将数组写入AT24C02
******************************************/
void Write_nums(uchar table[]){
int x=10;
while(x--){ Write_add(0x00,table[0]); Write_add(0x00,table[0]);
Write_add(0x10,table[1]); Write_add(0x10,table[1]);
Write_add(0x20,table[2]); Write_add(0x20,table[2]);
Write_add(0x30,table[3]); Write_add(0x30,table[3]);
Write_add(0x40,table[4]); Write_add(0x40,table[4]);
Write_add(0x50,table[5]); Write_add(0x50,table[5]);} }
/****************************************
主函数
****************************************/
void main(){ uchar k=0,j=0;
// Write_nums(mima);
mima[0]=Read_add(0x00);mima[1]=Read_add(0x10);
mima[2]=Read_add(0x20);mima[3]=Read_add(0x30);
mima[4]=Read_add(0x40);mima[5]=Read_add(0x50);
time(); initinal();
for(k=0;k<6;k++){mima0[k]=kong[k];}
for(;strcmp(mima,mima0)!=0;){enter_password();enter(mima0);
if(strcmp(mima,mima0)==0||strcmp(table1,mima0)==0){
welcome();P36=0;delay1(20);if(strcmp(table1,mima0)==0)break;}
else {password_error();for(k=0;k<6;k++){mima0[k]=kong[k];}
i++;delay1(20); if(i>=5){write_1602com(0x01);write_1602com(0x0c);while(1)warn();}}}
while(1){ j=key_gn();time_50ms=0;time_1s=0;
if(j=='c'){ for(k=0;k<6;k++){mima1[k]=kong[k];}
for(k=0;k<6;k++){mima2[k]=kong[k];}
for(k=0;k<6;k++){mima3[k]=kong[k];}
for(;strcmp(mima,mima1)!=0;){
old_password();
enter(mima1);
if(strcmp(mima,mima1)==0||strcmp(table1,mima1)==0){
new_password();enter(mima2);
enter_again();enter(mima3);
if(strcmp(mima2,mima3)==0){
modify_success();
for(k=0;k<6;k++){mima[k]=mima2[k];}
Write_nums(mima);welcome();break;}
else {enter_error();delay1(20);welcome();break;}}
else{password_error();delay1(20);i++;
if(i>=5){write_1602com(0x01);write_1602com(0x0c);while(1)warn();}} }}
if(j=='d')P36=1; }}