1 矩陣按鍵介紹
4*4矩陣按鍵,又稱行列式鍵盤,它用4條I/O線作為行線,它用4條I/O線作為列線組成鍵盤。在行線和列線的每一個交叉點上設置一個按鍵,這樣鍵盤按鍵就有4*4個,這種行列式鍵盤結構能夠有效的提高單片機系統的I/O口利用率。
2 功能要求:通過數碼管顯示矩陣按鍵S1-S16按下后鍵值0-F。
3 硬件設計
3.1 系統框圖
3.2 矩陣按鍵和數碼管電路
4 軟件設計
4.1 行列式掃描法
即逐行掃描:通過高四位輪流輸出低電平來對矩陣按鍵進行逐行掃描,當低四位接收到的數據不全為1的時候,說明有按鍵按下,然后通過接受到的數據是哪一位為0來判斷是哪一個按鍵被按下。

1 #include "reg52.h" 2 3 typedef unsigned int u16; 4 typedef unsigned char u8; 5 6 #define KEY_MATRIX_PORT P1 //矩陣按鍵控制端口 7 #define SMG_SEG_PORT P0 //數碼管段選控制端口 8 9 u8 gsmg_code[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 10 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-F的字形碼,共陰型數碼管 11 12 //延時函數,ten_us=1時,大約延時10us 13 void delay_10us(u16 ten_us) 14 { 15 while(ten_us--); 16 } 17 18 //矩陣按鍵掃描函數,采用行列式掃描法,監測按鍵是否按下,返回對應值 19 u8 key_matrix_ranks_scan(void) 20 { 21 u8 key_value=0; //存儲按鍵值 22 23 //從第一列開始,監測第1、2、3、4行,是否有按鍵按下 24 KEY_MATRIX_PORT=0xf7; //0B1111_0111,給第一列賦值0,其余為1 25 if(KEY_MATRIX_PORT!=0xf7) //判斷第一列是否按鍵按下 26 { 27 delay_10us(1000); //延時10ms,濾除按下抖動區域 28 switch(KEY_MATRIX_PORT) //返回第一列按鍵按下后的鍵值 29 { 30 case 0x77: key_value=1;break; //0B0111_0111 31 case 0xb7: key_value=5;break; //0B1011_0111 32 case 0xd7: key_value=9;break; //0B1101_0111 33 case 0xe7: key_value=13;break; //0B1110_0111 34 } 35 } 36 while(KEY_MATRIX_PORT!=0xf7); //等待按鍵松開 37 38 39 //從第二列開始,監測第1、2、3、4行,是否有按鍵按下 40 KEY_MATRIX_PORT=0xfb; //0B1111_1011,給第二列賦值0,其余為1 41 if(KEY_MATRIX_PORT!=0xfb) //判斷第二列是否按鍵按下 42 { 43 delay_10us(1000); //延時10ms,濾除按下抖動區域 44 switch(KEY_MATRIX_PORT) //返回第二列按鍵按下后的鍵值 45 { 46 case 0x7b: key_value=2;break; //0B0111_1011 47 case 0xbb: key_value=6;break; //0B1011_1011 48 case 0xdb: key_value=10;break; //0B1101_1011 49 case 0xeb: key_value=14;break; //0B1110_1011 50 } 51 } 52 while(KEY_MATRIX_PORT!=0xfb); //等待按鍵松開 53 54 //從第三列開始,監測第1、2、3、4行,是否有按鍵按下 55 KEY_MATRIX_PORT=0xfd; //0B1111_1101,給第三列賦值0,其余為1 56 if(KEY_MATRIX_PORT!=0xfd) //判斷第三列是否按鍵按下 57 { 58 delay_10us(1000); //延時10ms,濾除按下抖動區域 59 switch(KEY_MATRIX_PORT) //返回第三列按鍵按下后的鍵值 60 { 61 case 0x7d: key_value=3;break; //0B0111_1101 62 case 0xbd: key_value=7;break; //0B1011_1101 63 case 0xdd: key_value=11;break; //0B1101_1101 64 case 0xed: key_value=15;break; //0B1110_1101 65 } 66 } 67 while(KEY_MATRIX_PORT!=0xfd); //等待按鍵松開 68 69 70 //從第四列開始,監測第1、2、3、4行,是否有按鍵按下 71 KEY_MATRIX_PORT=0xfe; //0B1111_1110,給第一列賦值0,其余為1 72 if(KEY_MATRIX_PORT!=0xfe) //判斷第四列是否按鍵按下 73 { 74 delay_10us(1000); //延時10ms,濾除按下抖動區域 75 switch(KEY_MATRIX_PORT) //返回第四列按鍵按下后的鍵值 76 { 77 case 0x7e: key_value=4;break; //0B0111_0111 78 case 0xbe: key_value=8;break; //0B1011_0111 79 case 0xde: key_value=12;break; //0B1101_0111 80 case 0xee: key_value=16;break; //0B1110_0111 81 } 82 } 83 while(KEY_MATRIX_PORT!=0xfe); //等待按鍵松開 84 85 return key_value; 86 } 87 88 void main() 89 { 90 u8 key=0; 91 while(1) 92 { 93 key=key_matrix_ranks_scan(); 94 if(key!=0) 95 SMG_SEG_PORT=gsmg_code[key-1]; 96 } 97 }
4.2 線翻轉法
行列掃描:通過高四位全部輸出低電平,低四位輸出高電平。當接受到的數據,低四位不全為高電平時,說明有按鍵按下,然后通過接受的數據值,判斷是按一列按鍵按下,然后再反過來,高四位輸出高電平,低四位輸出低電平,然后根據接收到的高四位的值判斷是哪一行有按鍵按下,這樣就能夠確定是哪一個按鍵按下了。

1 #include "reg52.h" 2 3 typedef unsigned int u16; 4 typedef unsigned char u8; 5 6 #define KEY_MATRIX_PORT P1 //矩陣按鍵控制端口 7 #define SMG_SEG_PORT P0 //數碼管段選控制端口 8 9 u8 gsmg_code[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 10 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-F的字形碼,共陰型數碼管 11 12 //延時函數,ten_us=1時,大約延時10us 13 void delay_10us(u16 ten_us) 14 { 15 while(ten_us--); 16 } 17 18 //矩陣按鍵掃描函數,采用線翻轉掃描方法 19 u8 key_matrix_flip_scan(void) 20 { 21 static u8 key_value=0; //存儲按鍵值 22 KEY_MATRIX_PORT=0x0f; //給所有行賦值0,列全為1,即0b0000_1111 23 if(KEY_MATRIX_PORT!=0x0f) //判斷按鍵是否按下 24 { 25 delay_10us(1000); //消抖 26 if(KEY_MATRIX_PORT!=0x0f) 27 { 28 //測試列 29 KEY_MATRIX_PORT=0x0f; //0b0000_1111 30 switch(KEY_MATRIX_PORT) 31 { 32 case 0x07: key_value=1;break; //監測到第1列有按鍵按下 33 case 0x0b: key_value=2;break; //監測到第2列有按鍵按下 34 case 0x0d: key_value=3;break; //監測到第3列有按鍵按下 35 case 0x0e: key_value=4;break; //監測到第4列有按鍵按下 36 } 37 38 //測試行 39 KEY_MATRIX_PORT=0xf0; //1111_0000 40 switch(KEY_MATRIX_PORT) 41 { 42 case 0x70: key_value=key_value;break; //監測到第1行有按鍵按下 43 case 0xb0: key_value=key_value+4;break; //監測到第2行有按鍵按下 44 case 0xd0: key_value=key_value+8;break; //監測到第3行有按鍵按下 45 case 0xe0: key_value=key_value+12;break; //監測到第4行有按鍵按下 46 } 47 while(KEY_MATRIX_PORT!=0xf0); 48 } 49 } 50 else 51 key_value=0; 52 return key_value; 53 } 54 55 void main() 56 { 57 u8 key=0; 58 while(1) 59 { 60 key=key_matrix_flip_scan(); 61 if(key!=0) 62 SMG_SEG_PORT=gsmg_code[key-1]; 63 } 64 }
5 實驗現象:當按下S1-S16鍵,數碼管對應顯示0-F。
參考資料
(1)(79條消息) 51單片機(V51)———獨立按鍵、4x4矩陣按鍵_正弦定理的博客-CSDN博客;