獨(dú)立按鍵,一個按鍵需要占用一個I/O口,如果需要16個按鍵,那么就會 占用16個I/O口,占據(jù)MCS-51系列單片機(jī)一半的I/O口。
理論基礎(chǔ)
為了解決I/O這個問題,設(shè)計(jì)出了矩陣鍵盤,下圖是一個4*4的矩陣鍵盤原理圖。
按鍵按照4*4的格局進(jìn)行擺放,組成4行4列,將按鍵的同行或同列連接在一起,分別連接到P1口。
怎么才能識別是哪個按鍵被按下呢?
以上圖的S1為例,當(dāng)按鍵被按下S1導(dǎo)通,P17與P13導(dǎo)通,可以通過判斷P17與P13端口的電平是否一致,判斷按鍵是否被按下。
可以先設(shè)置P13(檢測端口)電平為高電平,假設(shè)P17(驅(qū)動端口)為低電平,當(dāng)按鍵按下,按鍵導(dǎo)通,讀取P13的電平可以讀到低電平。
(1)設(shè)置驅(qū)動端口電平為高電平(1)或者低電平(0);
(2)判斷檢測端口電平是否與驅(qū)動端口的電平一致;
實(shí)踐演練
P2口連接8個LED(如下圖所示),P1口連接為4*4的矩陣鍵盤(如前面的矩陣鍵盤所示),當(dāng)按鍵被按下時,P2口的LED點(diǎn)亮,點(diǎn)亮的LED與按鍵的鍵值一致。
寫代碼邏輯代碼先確定S1功能的實(shí)現(xiàn),然后以S1寫其他的按鍵的代碼。
假設(shè)設(shè)置P17為驅(qū)動端口,設(shè)置P13為檢測端口。初始化時P17口與P13檢測口初始狀態(tài)均為0,然后設(shè)置P17口為1,檢測P13是否變?yōu)楦唠娖?,?dāng)變?yōu)楦唠娖綍r,說明有按鍵被按下,代碼如下。
#include "reg52.h"
sbit driver_key1 = P1^7;
sbit snesor_key1 = P1^3;
void main() {
P2=0xff; //初始化P2口,P2口原有的數(shù)據(jù)影響
P1=0; //清空P1口,防止原有數(shù)據(jù)影響
while(1) {
char num=0; //設(shè)置鍵值
driver_key1 = 1; //驅(qū)動端口電平為1,驅(qū)動開始
if(snesor_key1==1) //判斷檢測端口是否為1,如果為1則按鍵被按下。
num = 1; //設(shè)置鍵值
driver_key1 = 0; //驅(qū)動端口電平為0,驅(qū)動結(jié)束
P2 =~num;
//由于I/O為低電平時,才可以被點(diǎn)亮。
//1的值換成二進(jìn)制00000001,其余七個led被點(diǎn)亮第一個不亮,
//需要第一個led被點(diǎn)亮需要將1取反,二進(jìn)制數(shù)變?yōu)?111 1110,第一個led亮。
}
}
使用上述代碼,燒錄程序后。LED燈不亮,按下按鍵S1,LED1也沒有亮。這是由于按鍵按下時,P17驅(qū)動端的高電平,會被P13檢測端的低電平拉成低電平,檢測端口檢測不到高電平。
將代碼修改為初始化時P17口與P13檢測口初始狀態(tài)均為1,然后設(shè)置P17口為0,檢測P13是否變?yōu)榈碗娖?,?dāng)變?yōu)榈碗娖綍r,說明有按鍵被按下,修改代碼如下。
void main() {
P2=0xff; //初始化P2口,P2口原有的數(shù)據(jù)影響
P1=0xff; //P1口置1,防止原有數(shù)據(jù)影響
while(1) {
char num=0; //設(shè)置鍵值
driver_key1 = 0; //驅(qū)動端口電平為0,驅(qū)動開始
if(snesor_key1==0) //判斷檢測端口是否為1,如果為1則按鍵被按下。
num = 1; //設(shè)置鍵值
driver_key1 = 1; //驅(qū)動端口電平為0,驅(qū)動結(jié)束
P2 =~num;
//由于I/O為低電平時,才可以被點(diǎn)亮。
//1的值換成二進(jìn)制00000001,其余七個led被點(diǎn)亮第一個不亮,
//需要第一個led被點(diǎn)亮需要將1取反,二進(jìn)制數(shù)變?yōu)?111 1110,第一個led亮。
}
}
編譯燒錄程序,當(dāng)按下S1時,可以實(shí)現(xiàn)LED1被點(diǎn)亮。
將按鍵檢測代碼獨(dú)立拉出來寫成函數(shù),實(shí)現(xiàn)16個按鍵,按壓時對應(yīng)的led被點(diǎn)亮,代碼如下。
#include "reg52.h"
sbit driver_key1 = P1^7;
sbit driver_key2 = P1^6;
sbit driver_key3 = P1^5;
sbit driver_key4 = P1^4;
sbit snesor_key1 = P1^3;
sbit snesor_key2 = P1^2;
sbit snesor_key3 = P1^1;
sbit snesor_key4 = P1^0;
char key_scan() {
char num =0;
driver_key1 = 0;
if(snesor_key1==0)
num = 1;
if(snesor_key2==0)
num = 2;
if(snesor_key3==0)
num = 3;
if(snesor_key4==0)
num = 4;
driver_key1 = 1;
driver_key2 = 0;
if(snesor_key1==0)
num = 5;
if(snesor_key2==0)
num = 6;
if(snesor_key3==0)
num = 7;
if(snesor_key4==0)
num = 8;
driver_key2 = 1;
driver_key3 = 0;
if(snesor_key1==0)
num = 9;
if(snesor_key2==0)
num = 10;
if(snesor_key3==0)
num = 11;
if(snesor_key4==0)
num = 12;
driver_key3 = 1;
driver_key4 = 0;
if(snesor_key1==0)
num = 13;
if(snesor_key2==0)
num = 14;
if(snesor_key3==0)
num = 15;
if(snesor_key4==0)
num = 16;
driver_key4 = 1;
return num;
}
void main() {
P2=0xff; //初始化P2口,P2口原有的數(shù)據(jù)影響
P1=0xff; //清空P1口,防止原有數(shù)據(jù)影響
while(1) {
char num =0;
num = key_scan();
P2 =~num;
//由于I/O為低電平時,才可以被點(diǎn)亮。
//1的值換成二進(jìn)制00000001,其余七個led被點(diǎn)亮第一個不亮,
//需要第一個led被點(diǎn)亮需要將1取反,二進(jìn)制數(shù)變?yōu)?111 1110,第一個led亮。
}
}
總結(jié):
(1)獨(dú)立按鍵使用簡單,如果項(xiàng)目中需要多個獨(dú)立按鍵就會很浪費(fèi)I/O資源;
(2)矩陣鍵盤通過判斷按鍵兩端的I/O是否一致,判斷按鍵是否被按下;
(3)按鍵按下時,驅(qū)動端口的高電平會被檢測端口的低電平拉低;
(4)對同一個功能可以寫成函數(shù),需要時進(jìn)行函數(shù)調(diào)用,看代碼時更有邏輯性。
-
單片機(jī)
+關(guān)注
關(guān)注
6067文章
44992瀏覽量
650502 -
51單片機(jī)
+關(guān)注
關(guān)注
277文章
5711瀏覽量
127393 -
矩陣鍵盤
+關(guān)注
關(guān)注
7文章
207瀏覽量
32116 -
獨(dú)立按鍵
+關(guān)注
關(guān)注
1文章
45瀏覽量
11842
發(fā)布評論請先 登錄
C51單片機(jī)矩陣鍵盤設(shè)計(jì)程序的詳細(xì)資料免費(fèi)下載

51單片機(jī)矩陣鍵盤的原理說明和實(shí)驗(yàn)程序及電路圖免費(fèi)下載
使用51單片機(jī)矩陣鍵盤模擬密碼鎖的C語言程序免費(fèi)下載

51單片機(jī)-矩陣鍵盤模塊-長短按鍵&數(shù)碼管顯示-模塊化編程模板

評論