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