這段程序是摘錄的51hei單片機論壇的教程,這里有個說明中斷函數中掃描 KeyIn 輸入和切換 KeyOut 輸出的順序與前面提到的順序不同,程序中我首先對所有的 KeyIn 輸入做了掃描、消抖,然后才切換到了下一次的 KeyOut 輸出,也就是說我們中斷每次掃描的實際是上一次輸出選擇的那行按鍵,這是為什么呢?因為任何信號從輸出到穩定都需要一個時間,有時它足夠快而有時卻不夠快,這取決于具體的電路設計,我們這里的輸入輸出順序的顛倒就是為了讓輸出信號有足夠的時間(一次中斷間隔)來穩定,并有足夠的時間來完成它對輸入的影響,當你的按鍵電路中還有硬件電容消抖時,這樣處理就是絕對必要的了,雖然這樣使得程序理解起來有點繞,但它的適應性是最好的,換個說法就是,這段程序足夠“健壯”,足以應對各種惡劣情況 。
這里我不太明白,一開始進入中斷的時候,keyout等于0,然后程序往下跑,keyout++,等于1了,case1,打開的是第二行。但是第二行并沒有被拉低為0啊,這里不知道是為什么?
不過我查閱了別的一些51的教程,關于矩陣按鍵這塊,貌似沒看到這么操作的,很是納悶,有這個必要嗎?別的程序都沒這么寫,包括它處理按鍵去抖的這個方法,哪種才是最優的呢?是這種還是別人直接寫個delay()多少毫秒那種呢?
單片機源程序如下:
void InterruptTimer0() interrupt 1
{
unsigned char i;
static unsigned char keyout = 0; //矩陣按鍵掃描輸出索引
static unsigned char keybuf[4][4] = { //矩陣按鍵掃描緩沖區
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
};
TH0 = 0xFC;
TL0 = 0x67; | //重新加載初值 |
//將一行的 4 個按鍵值移入緩沖區
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
//消抖后更新按鍵狀態
for (i=0; i<4; i++) //每行 4 個按鍵,所以循環 4 次
{
if ((keybuf[keyout][ i] & 0x0F) == 0x00)
{ //連續 4 次掃描值為 0,即 4*4ms 內都是按下狀態時,可認為按鍵已穩定的按下
KeySta[keyout][ i] = 0;
}
else if ((keybuf[keyout][ i] & 0x0F) == 0x0F)
{ //連續 4 次掃描值為 1,即 4*4ms 內都是彈起狀態時,可認為按鍵已穩定的彈起
KeySta[keyout][ i] = 1;
[ i]}
[ i]}
//執行下一次的掃描輸出
keyout++; //輸出索引遞增
keyout = keyout & 0x03; //索引值加到 4 即歸零
switch (keyout) //根據索引,釋放當前輸出引腳,拉低下次的輸出引腳
{
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
default: break;
}
}
|