第14集
鍵盤的原理
鍵盤分編碼鍵盤(例如電腦鍵盤)和非編碼鍵盤(自己用程序去識別)。
非編碼鍵盤分:獨立式非編碼鍵盤(獨立按鍵)、行列式非編碼鍵盤(4*4陣列鍵盤)
因為51單片機的IO口不是雙向口而是準雙向口,要讓IO口具備輸入功能,必須將IO口置1,置1之后當按鍵按下時IO口的電平會被拉低,即被置0。當檢測到IO口為0時即可判斷該按鍵已經按下。按鍵按下時會有一個抖動的過程(彈片會抖動),由于單片機檢測 IO口速度非常快,超過彈片抖動的頻率,所以當單片機檢測到IO口為0時需延時一小段時間再檢測IO是否為0,如果仍為0就確認該按鈕被按下。因為IO口里面有上拉電阻,所以當松開按鈕時,IO口又被拉高。
例程:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit Key = P3^4; // 按鍵
sbit Led = P1^0; // Led 燈
void delay(uint z);
/******** 主函數 ********/
void main()
{
while(1)
{
if(!Key)
{
delay(10); // 消抖操作
if(!Key)
Led = 0; // 按下時 Led亮
else
Led = 1;
}
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
第15集
4*4矩陣鍵盤
上圖中,1個按鍵占用一個IO口,如果有16個按鍵就占用了16個IO口。為了減少IO口的使用,就需要用矩陣的方式連線。如下圖
矩陣掃描原理
從圖可以看出P30、P31、P32、P33 為行(低四位),P34、P35、P36、P37為列(高四位)。
假設我們按下的是S6按鈕。
第一步,我們先確定列,給P3口賦值0xF0 = 1111 0000 ,那么P37、P36、P35、P34都被置1,P33、P32、P31、P30 都被置0,當S6被按下時,由于S6按鈕的一邊P31為0,所以跟S6另一邊相連的P35被拉低,即等于0。如下圖
此時得到列的值 P3 = 1101 0000 = 0xD0,在程序中只需要判斷P3是否等于0xF0,不等說明有按鍵按下。
第二步,不改變高四位的狀態:1101 將低四位全部置1(P3 = P3 | 0x0F)。這時候就變成了 1101 1111,由于單片機掃描列的時候速度非常快,到現在掃描行的時候,按鍵仍處在按下狀態(人的反應沒有單片機快)。S6被按下,由于與S6相連的P35為低電平(即0),所以P31由高電平(即1)變成低電平(即0)如下圖
此時得到的值為 P3 = 1101 1101 = S6 被按下。這就是檢測原理。
完整程序:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit Led = P1^0;
sbit Led1 = P1^1;
void delay(uint z);
/******** 主函數 ********/
void main()
{
uchar Key_Temp;
uchar Key; // Key 鍵值
while(1)
{
Key = 0; // 清0
P3 = 0xF0;
Key_Temp = P3;
Key_Temp &= 0xF0; // 只取高四位 這句需要,因為51IO只是準雙向 要使其具備輸入功能需要用置1
if(0xF0!=Key_Temp) // 判斷是否有按鍵按下
{
delay(10); // 延時一段時間 跳過抖動的時間
Key_Temp = P3 & 0xF0 ; // 先取P3 然后 和 0xF0與運算得到 高四位
if(0xF0 != Key_Temp) // 再次判斷是否確實按下
{
P3 = Key_Temp | 0x0F; // 保留高四位 將低四位全部置1 并輸出
Key = P3; // 再讀入
}
}
switch(Key)
{
case 0xEE: Led = 0; break; // S1
case 0xDE: Led1 = 0; break;
case 0xBE: break;
case 0x7E: break;
case 0xED: break;
case 0xDD: break;
case 0xBD: break;
case 0x7D: break;
case 0xEB: break;
case 0xDB: break;
case 0xBB: break;
case 0x7B: break;
case 0xE7: break;
case 0xD7: break;
case 0xB7: break;
case 0x77: break; // S16
default:
Led = Led1 = 1;
}
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}