A. 單片機電子密碼鎖設計,採用4×4鍵盤實現密碼的輸入功能,當密碼輸入正確之後,鎖就打開,如果輸入的密碼
#include <reg52.h>
#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;
}