獨立按鍵,一個按鍵需要占用一個I/O口,如果需要16個按鍵,那么就會 占用16個I/O口,占據MCS-51系列單片機一半的I/O口。
理論基礎
為了解決I/O這個問題,設計出了矩陣鍵盤,下圖是一個4*4的矩陣鍵盤原理圖。
按鍵按照4*4的格局進行擺放,組成4行4列,將按鍵的同行或同列連接在一起,分別連接到P1口。
怎么才能識別是哪個按鍵被按下呢?
以上圖的S1為例,當按鍵被按下S1導通,P17與P13導通,可以通過判斷P17與P13端口的電平是否一致,判斷按鍵是否被按下。
可以先設置P13(檢測端口)電平為高電平,假設P17(驅動端口)為低電平,當按鍵按下,按鍵導通,讀取P13的電平可以讀到低電平。
(1)設置驅動端口電平為高電平(1)或者低電平(0);
(2)判斷檢測端口電平是否與驅動端口的電平一致;
實踐演練
P2口連接8個LED(如下圖所示),P1口連接為4*4的矩陣鍵盤(如前面的矩陣鍵盤所示),當按鍵被按下時,P2口的LED點亮,點亮的LED與按鍵的鍵值一致。
寫代碼邏輯代碼先確定S1功能的實現,然后以S1寫其他的按鍵的代碼。
假設設置P17為驅動端口,設置P13為檢測端口。初始化時P17口與P13檢測口初始狀態均為0,然后設置P17口為1,檢測P13是否變為高電平,當變為高電平時,說明有按鍵被按下,代碼如下。
#include "reg52.h"
sbit driver_key1 = P1^7;
sbit snesor_key1 = P1^3;
void main() {
P2=0xff; //初始化P2口,P2口原有的數據影響
P1=0; //清空P1口,防止原有數據影響
while(1) {
char num=0; //設置鍵值
driver_key1 = 1; //驅動端口電平為1,驅動開始
if(snesor_key1==1) //判斷檢測端口是否為1,如果為1則按鍵被按下。
num = 1; //設置鍵值
driver_key1 = 0; //驅動端口電平為0,驅動結束
P2 =~num;
//由于I/O為低電平時,才可以被點亮。
//1的值換成二進制00000001,其余七個led被點亮第一個不亮,
//需要第一個led被點亮需要將1取反,二進制數變為1111 1110,第一個led亮。
}
}
使用上述代碼,燒錄程序后。LED燈不亮,按下按鍵S1,LED1也沒有亮。這是由于按鍵按下時,P17驅動端的高電平,會被P13檢測端的低電平拉成低電平,檢測端口檢測不到高電平。
將代碼修改為初始化時P17口與P13檢測口初始狀態均為1,然后設置P17口為0,檢測P13是否變為低電平,當變為低電平時,說明有按鍵被按下,修改代碼如下。
void main() {
P2=0xff; //初始化P2口,P2口原有的數據影響
P1=0xff; //P1口置1,防止原有數據影響
while(1) {
char num=0; //設置鍵值
driver_key1 = 0; //驅動端口電平為0,驅動開始
if(snesor_key1==0) //判斷檢測端口是否為1,如果為1則按鍵被按下。
num = 1; //設置鍵值
driver_key1 = 1; //驅動端口電平為0,驅動結束
P2 =~num;
//由于I/O為低電平時,才可以被點亮。
//1的值換成二進制00000001,其余七個led被點亮第一個不亮,
//需要第一個led被點亮需要將1取反,二進制數變為1111 1110,第一個led亮。
}
}
編譯燒錄程序,當按下S1時,可以實現LED1被點亮。
將按鍵檢測代碼獨立拉出來寫成函數,實現16個按鍵,按壓時對應的led被點亮,代碼如下。
#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口原有的數據影響
P1=0xff; //清空P1口,防止原有數據影響
while(1) {
char num =0;
num = key_scan();
P2 =~num;
//由于I/O為低電平時,才可以被點亮。
//1的值換成二進制00000001,其余七個led被點亮第一個不亮,
//需要第一個led被點亮需要將1取反,二進制數變為1111 1110,第一個led亮。
}
}
總結:
(1)獨立按鍵使用簡單,如果項目中需要多個獨立按鍵就會很浪費I/O資源;
(2)矩陣鍵盤通過判斷按鍵兩端的I/O是否一致,判斷按鍵是否被按下;
(3)按鍵按下時,驅動端口的高電平會被檢測端口的低電平拉低;
(4)對同一個功能可以寫成函數,需要時進行函數調用,看代碼時更有邏輯性。
-
單片機
+關注
關注
6037文章
44558瀏覽量
635304 -
51單片機
+關注
關注
274文章
5702瀏覽量
123617 -
矩陣鍵盤
+關注
關注
7文章
206瀏覽量
31471 -
獨立按鍵
+關注
關注
1文章
45瀏覽量
11563
發布評論請先 登錄
相關推薦
評論