#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define setb(val,bitn) (val|=(1<<(bitn)))//設置某IO口某位為1,即設置IO口進行位操縱
#define clr(val,bitn) (val&=~(1<<(bitn)))//設置某IO口某位為0 即設置IO口進行位操縱
#define get(val,bitn) (val&(1<<(bitn)))//讀取某位狀態(tài)如if(get(PORTC,7))即判斷PC7口是否為1 即設置IO口進行位操縱
#pragma data:code//定義程序存在ROM里面
uchar yin,yin1,yin2,yin3;//4位密碼初始變量
uchar qing,qing1,qing2,qing3;//4位密碼比較變量
uchar num;//按鍵按下次數(shù)變量
uchar temp;//比較標志位變量,即按下后比較變量與初始密碼變量比較,如果是相等,則些標志位生效,它自動變量加1
const table[]={
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,
0x8e,0xff
};
/***********************************************/
/*******************延時子程序******************/
/***********************************************/
void delay(uint z)
{
uint x,y;
for(x=0;x<50;x++)
for(y=0;y<z;y++);
}
/***********************************************/
/*****************蜂鳴器響子程序****************/
/***********************************************/
void bbt()
{
setb(DDRA,1);
clr(PORTA,1);
delay(2550);
setb(PORTA,1);
delay(2550);
}
/***********************************************/
/*******************顯示子程序******************/
/***********************************************/
void xian(uchar num)
{
uchar i;
PORTB=table[num];
PORTC=0x00;//打開位選端
}
/***********************************************/
/***************按鍵按下處理程序***************/
/***********************************************/
uchar key_press()
{
uchar i;
DDRD=0XFF;//設置PD口全為輸出
PORTD=0XF0;//設置PD高四位為高電平,以便進行判斷
DDRD=0X0F;//設置高4位為輸入,低4位為輸出
i=PIND;//讀出IO口狀態(tài)
if(i==0XF0)//如果它等于0XF0就執(zhí)返回0
{
DDRD=0XFF;//將IO口值讀回來
return 0;
}
else//否則它就執(zhí)返回1
{
DDRD=0XFF;
return 1;
}
}
/***********************************************/
/***************按鍵鍵值處理程序***************/
/***********************************************/
uchar key_scan()
{
uchar key,i=0X7F,j;//將變量I設置為01111111B
if(key_press())//判斷按鍵是否被按下了
{
delay(10);//如果被按下了,消下抖
if(key_press())//再次判斷下按鍵是否被按下了
{
do//先執(zhí)行一次
{
i=(i<<1|i>>7);/*將變量I內容左移1位,11111110
然后將I右移7位,11111110,即實現(xiàn)11111110
11111101 11111011 11110111*/
PORTD=i;//將移位后的值給PD口
DDRD=0X0F;//將PD口高位設為輸入,低位設為輸出
key=PIND;//將IO口高位值讀一下
j=key&0XF0;//只需要讀高4位
}
while(j==0XF0);//如果按鍵沒有按下,則再執(zhí)行上面的do語句
while(key_press());//如果有按下則釋放一下
num++;//計數(shù)改變變量值
//if(num>3)
//num=0;
switch(key)//確定有按鍵按下了就判斷下到底是哪個值
{
case 0xEE:qing=0;
key=0x0;
break;
case 0xDE:qing1=1;
key=0x1;
break;
case 0xBE:qing2=2;
key=0x2;
break;
case 0x7E:qing3=3;
key=0x3;
break;
case 0xED:
key=0x4;
break;
case 0xDD:
key=0x5;
break;
case 0xBD:
key=0x6;
break;
case 0x7D:
key=0x7;
break;
case 0xEB:
key=8;
break;
case 0xDB:
key=9;
break;
case 0xBB:
key=0xA;
break;
case 0x7B:
key=0xB;
break;
case 0xE7:
key=0xC;
break;
case 0xD7:
key=0xD;
break;
case 0xB7:
key=0xE;
break;
case 0x77:
key=0xF;
break;
}
}
}
return key;//返回按鍵值
}
/******************************************************/
/*******************密碼判斷子程序*********************/
/******************************************************/
void mi()
{
switch(num)
{
case 1://只有按鍵標志位為1時,說明按下的是第1次
if(qing==yin)//此時第1位密碼比較變量與初始密碼變量比較,是否相等
{
temp++;//如果相等則將比較標志位加1,以作記號
qing=0xff;//作完記號后,將比較變量賦值,以便它再次記數(shù)標志位變量
}
break;//返回
case 2://只有按鍵標志位為2時,說明按下的是第2次
if(qing1==yin1)
{
temp++;
qing1=0xff;
}
break;
case 3://只有按鍵標志位為3時,說明按下的是第3次
if(qing2==yin2)
{
temp++;
qing2=0xff;
}
break;
case 4://只有按鍵標志位為4時,說明按下的是第4次
if(qing3==yin3)
{
temp++;
qing3=0xff;
}
break;
}
if(temp==4)//如果比較標志位變量為4,則說明以上4個密碼是對的,此時蜂鳴器響起
bbt();//調用蜂鳴器響起子程序
}
/***********************************************/
/*******************主程序*********************/
/***********************************************/
void main()
{
uchar ik=16;//定義局部變量
temp=0;//蜂鳴器計數(shù)變量變0
num=0;//計數(shù)器清0
yin=0;//密碼1
yin1=1;//密碼2
yin2=2;//密碼3
yin3=3;//密碼4
qing=qing1=qing2=qing3=0;//密碼比較變量清0
DDRB=0xff;//設置PB口為輸出
DDRC=0xff;//設置PC口為輸出
while(1)
{
ik=key_scan();//將按鍵返回值給變量IK
/*****************第15個鍵按下時處理的程序*****************/
if(ik==15)//如果按下了第15個鍵,就將按下的次數(shù)清0,即進入初始化
{
num=0;//清0計數(shù)器
temp=0;//清0計數(shù)器
qing=qing1=qing2=qing3=0;//密碼比較變量清0
}
/*****************數(shù)碼管顯示部分*****************/
if(ik<16)//如果返回值小于16就在數(shù)碼
xian(ik); //調用顯示子程序
else//如果返回值不小于16,就顯示黑屏
xian(16);
/*****************密碼判斷部分*****************/
mima();
}
}