標題:
6條語句搞定16矩陣鍵盤掃描單片機C語言程序
[打印本頁]
作者:
a399288395
時間:
2023-2-26 12:04
標題:
6條語句搞定16矩陣鍵盤掃描單片機C語言程序
我自己寫了一段51單片機的代碼分享給大家,有完整的注釋,和解碼過程圖解,
這個矩陣鍵盤掃描程序不同于網(wǎng)上那些逐行掃描; 思路新穎,語句簡單,識別準確;
掃描子函數(shù)中包含變量定義,所有代碼就10行;真正做解碼的只用了6條語句
這段演示程序中沒有任何延時阻塞函數(shù);識別率挺高; 做項目最好加入中斷定時掃描;如果單片機資源緊張,也可以在1-3 或者4-7;4條IO口上對地加4個104電容做硬件消抖;
程序在下面,里面還有一個LCD1602的顯示函數(shù), 用來演示按鍵掃描結(jié)果!
單片機源程序如下:
#include <REGX51.H>
#include "LCD1602.H"
/*** 0-15鍵值 ***/
/*****************
0x77,0x7B,0x7D,0x7E
0xB7,0xBB,0xBD,0xBE
0xD7,0xDB,0xDD,0xDE
0xE7,0xEB,0xED,0xEE
******************/
unsigned char Key_Scan(); //按鍵掃描函數(shù)聲明
/* 主函數(shù)從這里開始 */
void main(void)
{
static unsigned char Key_Code = 0x00; //定義一個靜態(tài)變量
LCD_Init(); //初始化LCD1602,用來顯示鍵值
while(1)
{
Key_Code = Key_Scan();
switch (Key_Code) //演示示例;用switch語句操作鍵碼;比如我在1602液晶屏上顯示數(shù)字1-16;也可以用數(shù)組來操作,自由發(fā)揮!
{
case 0x77: LCD_ShowNum(1,2,1,2); break;
case 0x7B: LCD_ShowNum(1,2,2,2); break;
case 0x7D: LCD_ShowNum(1,2,3,2); break;
case 0x7E: LCD_ShowNum(1,2,4,2); break;
case 0xB7: LCD_ShowNum(1,2,5,2); break;
case 0xBB: LCD_ShowNum(1,2,6,2); break;
case 0xBD: LCD_ShowNum(1,2,7,2); break;
case 0xBE: LCD_ShowNum(1,2,8,2); break;
case 0xD7: LCD_ShowNum(1,2,9,2); break;
case 0xDB: LCD_ShowNum(1,2,10,2); break;
case 0xDD: LCD_ShowNum(1,2,11,2); break;
case 0xDE: LCD_ShowNum(1,2,12,2); break;
case 0xE7: LCD_ShowNum(1,2,13,2); break;
case 0xEB: LCD_ShowNum(1,2,14,2); break;
case 0xED: LCD_ShowNum(1,2,15,2); break;
case 0xEE: LCD_ShowNum(1,2,16,2); break;
default: break;
}
}
}
/* 帶返回值的按鍵掃描函數(shù)*/
unsigned char Key_Scan()
{
unsigned char Key_Temp; //定義一個存放組合鍵碼的變量
unsigned char Key_A,Key_B; // 定義兩個變量,Key_A 用于存放正向掃描的鍵碼; Key_B 用于存放反向掃描的鍵碼。
P1 = 0xF0; //把P1口的高4位(P1.4-P1.7)置高,低4位置低;(如果有按鍵按下 高4位肯定有一條線會被拉低)。
Key_Temp = P1; //把P1口的狀態(tài)讀回來,傳遞給Key_Temp。沒有按鍵按下Key_Temp肯定是0XF0; 否則就是其它的數(shù);
if(Key_Temp!= 0xF0) // 進入if判斷語句;如果Key_Temp不等于0XF0,說明有鍵按下了。
{
Key_A = P1; // 把P1口此時被按下的狀態(tài)傳遞給Key_A保存
P1 = 0x0F; //開始反轉(zhuǎn)掃描;把P1口的高4位置低,低4位(P1.0-P1.3)置高;(如果有按鍵按下 低4位肯定有一條線會被拉低)。
Key_B = P1; //把P1口此時被按下的狀態(tài)傳遞給Key_A保存
}
Key_Temp = (Key_A | Key_B); //把正反兩次掃描的結(jié)果相或, 就會得到按鍵按下的正確鍵碼
return Key_Temp; //把鍵碼返回,給其他的函數(shù)調(diào)用
}
//下面是圖解正反轉(zhuǎn)掃描的程序工作原理
/*
正向掃描,比如P1.7和P1.3連接的按鍵被按下 那么P1口的0XF0:1111 0000 就會變成0X70:0111 0000
P1.3 P1.2 P1.1 P1.0
0 0 0 0
P1.7 1 -+- --- --- ---
P1.6 1 --- --- --- ---
P1.5 1 --- --- --- ---
P1.4 1 --- --- --- ---
反向掃描,比如P1.7和P1.3連接的按鍵被按下 那么P1口的0X0F:0000 1111 就會變成0X07:0000 0111
P1.3 P1.2 P1.1 P1.0
1 1 1 1
P1.7 0 -+- --- --- ---
P1.6 0 --- --- --- ---
P1.5 0 --- --- --- ---
P1.4 0 --- --- --- ---
最后把 正反兩次掃描的結(jié)果 0X70 與0X07相或 就會得到0X77的鍵碼
只要得到正確的鍵碼,就可以用這個鍵碼做任何事情。比如我在液晶屏上顯示數(shù)字1;表示數(shù)字1鍵被按下。
*/
//下面這組鍵值根據(jù)不同的接線方式,會有不同的鍵值,需要提前自己算好;就類似數(shù)碼管的段碼一樣;也可以做成一個數(shù)組。
/*** 0-15鍵值 ***/
/*****************
0x77,0x7B,0x7D,0x7E
0xB7,0xBB,0xBD,0xBE
0xD7,0xDB,0xDD,0xDE
0xE7,0xEB,0xED,0xEE
******************/
復(fù)制代碼
Keil代碼下載:
6條語句搞定4X4矩陣按鍵.rar
(35.42 KB, 下載次數(shù): 45)
2023-2-26 12:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
wdgao
時間:
2023-2-26 15:48
簡單問題復(fù)雜化了,本來處理就是幾句話的事。
作者:
624353765
時間:
2023-2-26 18:31
跟我寫的非常接近了,但還能簡化,對于高速單片機這代碼行不通,給兩點建議:實時性和性能問題
作者:
szb314
時間:
2023-2-27 08:58
全鍵無沖沒解決
作者:
suiwinder
時間:
2023-2-27 13:45
個人看樓主的程序很好。樓上有好的想法和寫法的,可以分享下。
作者:
woodgo
時間:
2023-2-28 21:44
思路不錯
作者:
wulin
時間:
2023-3-9 10:01
還能再省一句
#include <REGX51.H>
#include "LCD1602.H"
/*** 0-15鍵值 ***/
/*****************
0x77,0x7B,0x7D,0x7E
0xB7,0xBB,0xBD,0xBE
0xD7,0xDB,0xDD,0xDE
0xE7,0xEB,0xED,0xEE
******************/
unsigned char Key_Scan(); //按鍵掃描函數(shù)聲明
/* 主函數(shù)從這里開始 */
void main(void)
{
// static unsigned char Key_Code = 0x00; //定義一個靜態(tài)變量
LCD_Init(); //初始化LCD1602,用來顯示鍵值
while(1)
{
// Key_Code = Key_Scan();
switch (Key_Scan()) //演示示例;用switch語句操作鍵碼;比如我在1602液晶屏上顯示數(shù)字1-16;也可以用數(shù)組來操作,自由發(fā)揮!
{
case 0x77: LCD_ShowNum(1,2,1,2); break;
case 0x7B: LCD_ShowNum(1,2,2,2); break;
case 0x7D: LCD_ShowNum(1,2,3,2); break;
case 0x7E: LCD_ShowNum(1,2,4,2); break;
case 0xB7: LCD_ShowNum(1,2,5,2); break;
case 0xBB: LCD_ShowNum(1,2,6,2); break;
case 0xBD: LCD_ShowNum(1,2,7,2); break;
case 0xBE: LCD_ShowNum(1,2,8,2); break;
case 0xD7: LCD_ShowNum(1,2,9,2); break;
case 0xDB: LCD_ShowNum(1,2,10,2); break;
case 0xDD: LCD_ShowNum(1,2,11,2); break;
case 0xDE: LCD_ShowNum(1,2,12,2); break;
case 0xE7: LCD_ShowNum(1,2,13,2); break;
case 0xEB: LCD_ShowNum(1,2,14,2); break;
case 0xED: LCD_ShowNum(1,2,15,2); break;
case 0xEE: LCD_ShowNum(1,2,16,2); break;
default: break;
}
}
}
/* 帶返回值的按鍵掃描函數(shù)*/
unsigned char Key_Scan()
{
unsigned char Key_Temp; //定義一個存放組合鍵碼的變量
// unsigned char Key_A,Key_B; // 定義兩個變量,Key_A 用于存放正向掃描的鍵碼; Key_B 用于存放反向掃描的鍵碼。
P1 = 0xf0; //把P1口的高4位(P1.4-P1.7)置高,低4位置低;(如果有按鍵按下 高4位肯定有一條線會被拉低)。
if(P1!= 0xf0) // 進入if判斷語句;如果Key_Temp不等于0XF0,說明有鍵按下了。
{
Key_Temp = P1; // 把P1口此時被按下的高4位狀態(tài)保存
P1 = 0x0f; //開始反轉(zhuǎn)掃描;把P1口的高4位置低,低4位(P1.0-P1.3)置高;(如果有按鍵按下 低4位肯定有一條線會被拉低)。
Key_Temp |= P1&0x0f; //把P1口此時被按下的低4位狀態(tài)與高4位狀態(tài)合并
}
return Key_Temp; //把鍵碼返回,給其他的函數(shù)調(diào)用
}
復(fù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1