?? l_key.c
字號:
/*鍵盤程序,本程序涉及到外中斷,定時器中斷,比較復(fù)雜,耐心學(xué),幫助了解中斷事件*/
#include <reg51.h>
#include <intrins.h>
sbit SPK=P3^4; //SPK定義為P3口的第4位,就是驅(qū)動蜂鳴器的那個腳
sbit JDQ=P3^5; //JDQ定義為P3口的第5位,就是驅(qū)動繼電器的那個腳
code unsigned char table[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
//共陰數(shù)碼管 0-9 a-f 表
code unsigned char key_tab[17]={0xed,0x7e,0x7d,0x7b,
0xbe,0xbd,0xbb,0xde,
0xdd,0xdb,0x77,0xb7,
0xee,0xd7,0xeb,0xe7,0XFF};//========================此數(shù)組為鍵盤編碼,
//本人采用類式類似電話按鍵的編碼方式,方便以后設(shè)計
// 1 2 3 a 0x01 0x02 0x03 0x0a
// 4 5 6 b 對應(yīng)16進(jìn)制碼: 0x04 0x05 0x06 0x0b
// 7 8 9 e 0x07 0x08 0x09 0x0e
// * 0 # f 0x0c 0x00 0x0e 0x0f
//打個比方,如果你按下0鍵,P0口讀到數(shù)據(jù)為0xed
//如果你按下2鍵,P0口讀到數(shù)據(jù)為0x7d,按下9鍵為0xdb,
//我們將讀到的P0口數(shù)據(jù)經(jīng)過查表法就能得到相應(yīng)的16進(jìn)制碼
//鍵盤的讀取,我們采用中斷法,電路用一個4與門(74HC21)接入
//中斷口(INT0),利用中斷來掃描鍵盤矩陣,讀取數(shù)據(jù)
unsigned char l_tmpdate[8]={0,0,0,0,0,0,0,0};//定義數(shù)組變量
unsigned char l_key=0x0; //定義變量,存放鍵值
unsigned char l_keyold=0xFF; //做為按鍵松開否的憑證
void ReadKey(void); //掃描鍵盤 獲取鍵值
void delay();//延時子函數(shù),5個空指令
void display(unsigned char *lp,unsigned char lc);//數(shù)字的顯示函數(shù);lp為指向數(shù)組的地址,lc為顯示的個數(shù)
//這個函數(shù)在第二節(jié)用過不用再說了吧!
void main(void) //入口函數(shù)
{
EA=1; //首先開啟總中斷
EX0=1; //開啟外部中斷 0
IT0=1; // 設(shè)置成 下降沿觸發(fā)方式
P0=0xf0; //P0口高位輸高電平,經(jīng)過74HC21四輸入與門,連接外中斷0,有鍵按下調(diào)用中斷函數(shù)
while(1){
display(&l_key,1); //輸出獲取的鍵值碼
if(l_key==0x0e) //這里我們檢測是否按了0x0e鍵,
JDQ=0; //是,我們就驅(qū)動繼電器打開
if(l_key==0x0c) //檢測是否按下了0x0c鍵,
JDQ=1; //是,我們就驅(qū)動繼電器斷開
}
}
void key_scan() interrupt 0 //外部中斷 0 0的優(yōu)先級最高
{
EX0=0; //在讀鍵盤期間,我們關(guān)閉中斷,防止干擾帶來的多次中斷
//為了消除抖動帶來的干擾,在按下鍵后我們采用延時十多毫秒再讀取鍵值
//如果采用循環(huán)語句來延時,比如(for,while。。。)會使CPU處理循環(huán)而占用
//系統(tǒng)資源,所以這里我們采用定時器中斷法,讓定時器等待十多毫秒觸發(fā)定時器
//中斷,這里用到定時器0
TMOD&=0XF1; //設(shè)置定時器0為模式1方式,
TH0=0X2E; //設(shè)置初值,為12毫秒
TL0=0X00;
ET0=1; //開啟定時器中斷0
TR0=1; //啟動定時器計數(shù)
}
void timer0_isr(void) interrupt 1 //定時器0的中斷函數(shù)
{
TR0=0; //中斷后我們停止計數(shù)
ReadKey(); //定時器計數(shù)12毫秒后產(chǎn)生中斷,調(diào)用此函數(shù),讀取鍵值
}
void ReadKey(void) //讀鍵盤值
unsigned char i,j,key;
j=0xfe;
key=0xff; //設(shè)定初值
for (i=0;i<4;i++){
P0=j; //P0口低4位循環(huán)輸出0,掃描鍵盤
//leday();
if ((P0&0xf0)!=0xf0){ //如果有鍵按下,P0口高4位不會為1,
key=P0; //讀取P0口,退出循環(huán),否則循環(huán)下次
break;
}
j=_crol_(j,1); //此函數(shù)功能為左循環(huán)移位
}
if (key==0xff){ //如果讀取不到P0口的值,比如是干擾,我們不做鍵值處理,返回
l_keyold=0xff;
//l_key=0xff;
P0=0xf0; //恢復(fù)P0口,等待按鍵按下
EX0=1; //返回之前,開啟外中斷
SPK=1;
return;
}
SPK=0; //有鍵按下,我們驅(qū)動蜂鳴器響
if(l_keyold==key){ //檢測按鍵放開否,如果一樣表明沒放開,
TH0=0X2E; //我們繼續(xù)啟動定時器,檢測按鍵松開否
TL0=0;
TR0=1;
return;
}
TH0=0X2E;
TL0=0;
TR0=1; //我們繼續(xù)啟動定時器,檢測按鍵松開否
l_keyold=key; //獲取鍵碼做為放開的憑證
for(i=0;i<17;i++){ //查表獲得相應(yīng)的16進(jìn)制值存放l_key變量中
if (key==key_tab[i]){
l_key=i;
break;
}
}
//程序運行到這里,就表明有鍵值被讀取存放于l_key變量中,主程序就可以檢測此變量做相應(yīng)外理,
//此時我們回到主程序
}
void display(unsigned char *lp,unsigned char lc)//顯示
{
unsigned char i; //定義變量
P2=0; //端口2為輸出
P1=P1&0xF8; //將P1口的前3位輸出0,對應(yīng)138譯門輸入腳,全0為第一位數(shù)碼管
for(i=0;i<lc;i++){ //循環(huán)顯示
P2=table[lp[i]]; //查表法得到要顯示數(shù)字的數(shù)碼段
delay(); //延時5個空指令
if(i==7) //檢測顯示完8位否,完成直接退出,不讓P1口再加1,否則進(jìn)位影響到第四位數(shù)據(jù)
break;
P2=0; //清0端口,準(zhǔn)備顯示下位
P1++; //下一位數(shù)碼管
}
}
void delay(void) //空5個指令
{
_nop_();_nop_();_nop_();_nop_();_nop_();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -