矩陣鍵盤是單片機(jī)外部設(shè)備中所使用的排布類似于矩陣的鍵盤組。矩陣式結(jié)構(gòu)的鍵盤顯然比直接法要復(fù)雜一些,識(shí)別也要復(fù)雜一些,列線通過電阻接正電源,并將行線所接的單片機(jī)的I/O口作為輸出端,而列線所接的I/O口則作為輸入。
矩陣鍵盤特點(diǎn)
矩陣鍵盤的編程是十分復(fù)雜的,但是矩陣鍵盤也節(jié)省IO口。而且還提高了I/O口利用率。
矩陣鍵盤構(gòu)成與工作方式
圖9-7為一個(gè)4x3的行列結(jié)構(gòu),可以構(gòu)成12個(gè)鍵的鍵盤。如果使用4x4的行列結(jié)構(gòu),就能組成一個(gè)16鍵的鍵盤。很明顯,在按鍵數(shù)量多的場(chǎng)合,矩陣鍵盤與獨(dú)立式按鍵鍵盤相比可以節(jié)省很多的I/O口線。
矩陣鍵盤不僅在連接上比單獨(dú)式按鍵復(fù)雜,它的按鍵識(shí)別方法也比單獨(dú)式按鍵復(fù)雜。在矩陣鍵盤的軟件接口程序中,常使用的按鍵識(shí)別方法有行掃描法和線反轉(zhuǎn)法。這兩種方法的基本思路是采用循環(huán)查循的方法,反復(fù)查詢按鍵的狀態(tài),因此會(huì)大量占用MCU的時(shí)間,所以較好的方式也是采用狀態(tài)機(jī)的方法來(lái)設(shè)計(jì),盡量減少鍵盤查詢過程對(duì)MCU的占用時(shí)間。
下面以圖9-7為例,介紹采用行掃描法對(duì)矩陣鍵盤進(jìn)行判別的思路。圖9-7中,PD0、PD1、PD2為3根列線,作為鍵盤的輸入口(工作于輸入方式)。PD3、PD4、PD5、PD6為4根行線,工作于輸出方式,由MCU(掃描)控制其輸出的電平值。行掃描法也稱為逐行掃描查詢法,其按鍵識(shí)別的過程如下。
√將全部行線PD3-PD6置低電平輸出,然后讀PD0-PD2三根輸入列線中
有無(wú)低電平出現(xiàn)。只要有低電平出現(xiàn),則說(shuō)明有鍵按下(實(shí)際編程時(shí),還要考慮按鍵的消抖)。如讀到的都是高電平,則表示無(wú)鍵按下。
√在確認(rèn)有鍵按下后,需要進(jìn)入確定具體哪一個(gè)鍵閉合的過程。其思路是:依次將行線置為低電平,并檢測(cè)列線的輸入(掃描),進(jìn)而確認(rèn)是具體的按鍵位置。如當(dāng)PD5輸出低電平時(shí)(PD3=1、PD4=1、PD5=0、PD6=1),測(cè)到PD1的輸入為低電平(PD0=1、PD1=0、PD2=1),則可確認(rèn)按鍵K3-2處于閉合狀態(tài)。通過以上分析可以看出,MCU對(duì)矩陣鍵盤的按鍵識(shí)別,是采用掃描方式控制行線的輸出和檢測(cè)列線輸入的信號(hào)相配合實(shí)現(xiàn)的。
√矩陣按鍵的識(shí)別僅僅是確認(rèn)和定位了行和列的交叉點(diǎn)上的按鍵,接下來(lái)還要
考慮鍵盤的編碼,即對(duì)各個(gè)按鍵進(jìn)行編號(hào)。在軟件中常通過計(jì)算的方法或查表的方法對(duì)按鍵進(jìn)行具體的定義和編號(hào)。
在單片機(jī)嵌入式系統(tǒng)中,鍵盤掃描只是MCU的工作內(nèi)容之一。MCU除了要檢測(cè)鍵盤和處理鍵盤操作之外,還要進(jìn)行其他事物的處理,因此,MCU如何響應(yīng)鍵盤的輸入需要在實(shí)際系統(tǒng)程序設(shè)計(jì)時(shí)認(rèn)真考慮。
通常,完成鍵盤掃描和處理的程序是系統(tǒng)程序中的一個(gè)專用子程序,MCU調(diào)用該鍵盤掃描子程序?qū)︽I盤進(jìn)行掃描和處理的方式有三種:程序控制掃描、定時(shí)掃描和中斷掃描。
√程序控制掃描方式。在主控程序中的適當(dāng)位置調(diào)用鍵盤掃描程序,對(duì)鍵盤進(jìn)
行讀取和處理。
√定時(shí)掃描方式。在該方式中,要使用MCU的一個(gè)定時(shí)器,使其產(chǎn)生一個(gè)
10ms的定時(shí)中斷,MCU響應(yīng)定時(shí)中斷,執(zhí)行鍵盤掃描,當(dāng)在連續(xù)兩次中斷中都讀到相同的按
√鍵按下(間隔10ms作為消抖處理),MCU才執(zhí)行相應(yīng)的鍵處理程序中斷
方式。使用中斷方式時(shí),鍵盤的硬件電路要做一定的改動(dòng),增加一個(gè)按鍵產(chǎn)生中斷信號(hào)的輸入線,當(dāng)鍵盤有按鍵按下時(shí),鍵盤硬件電路產(chǎn)生一個(gè)外部的中斷信號(hào),
MCU響應(yīng)外部中斷,進(jìn)行鍵盤處理。
下面我們介紹基于狀態(tài)機(jī)并采用定時(shí)鍵盤掃描的鍵盤處理系統(tǒng)的設(shè)計(jì)方法。
定時(shí)掃描方式的鍵盤接口程序
根據(jù)圖9-7,下面的鍵盤接口函數(shù)read_keyboaed()完成了對(duì)4*3鍵盤的掃描識(shí)別和鍵盤的編碼。編碼鍵盤的定義使用define語(yǔ)句定義,鍵盤的形式類似電話和手機(jī)鍵盤,如圖9-8所示。
#defineNo_key255
#defineK1_11
#defineK1_22
#defineK1_33
#defineK2_14
#defineK2_25
#defineK2_36
#defineK3_17
#defineK3_28
#defineK3_39
#defineK4_110
#defineK4_20
#defineK4_311
#defineKey_mask0b00000111
charread_keyboard()
{
staticcharkey_state=0,key_value,key_line;
charkey_return=No_key,i;
switch(key_state)
{
case0:
key_line=0b00001000;
for(i=1;i《=4;i++)//掃描鍵盤
PORTD=~key_line;//輸出行線電平
PORTD=~key_line;//必須送2次?。。。ㄗ?key_value=Key_mask&PIND;//讀列電平if(key_value==Key_mask)
key_line《《=1;//沒有按鍵,繼續(xù)掃描
else
{
key_state++;//有按鍵,停止掃描
break;//轉(zhuǎn)消抖確認(rèn)狀態(tài)
}
}
break;case1:
if(key_value==(Key_mask&PIND))//再次讀列電平,{
switch(key_line|key_value)//與狀態(tài)0的相同,確認(rèn)按鍵{//鍵盤編碼,返回編碼值case0b00001110:key_return=K1_1;break;
case0b00001101:
key_return=K1_2;break;
case0b00001011:
key_return=K1_3;break;
case0b00010110:
key_return=K2_1;break;
case0b00010101:key_return=K2_2;
break;
case0b00010011:
key_return=K2_3;break;
case0b00100110:
key_return=K3_1;break;
case0b00100101:
key_return=K3_2;break;
case0b00100011:
key_return=K3_3;break;
case0b01000110:
key_return=K4_1;
break;
case0b01000101:
key_return=K4_2;
break;
case0b01000011:
key_return=K4_3;
break;}
key_state++;//轉(zhuǎn)入等待按鍵釋放狀態(tài)
}
else
key_state--;//兩次列電平不同返回狀態(tài)0,(消抖處理)
break;
case2://等待按鍵釋放狀態(tài)
PORTD=0b00000111;//行線全部輸出低電平
PORTD=0b00000111;//重復(fù)送一次
if((Key_mask&PIND)==Key_mask)
key_state=0;//列線全部為高電平返回狀態(tài)0
break;
}
returnkey_return;
}
系統(tǒng)主程序應(yīng)每隔10ms調(diào)用該鍵盤接口函數(shù)read_keyboaed(),函數(shù)返回值為255時(shí)表示無(wú)按鍵按下。檢測(cè)和確認(rèn)按鍵按下時(shí),函數(shù)返回值為0到11之間的一個(gè),該返回值已經(jīng)是經(jīng)過了鍵盤編碼的值。
鍵盤接口函數(shù)read_keyboaed()是基于狀態(tài)機(jī)實(shí)現(xiàn)的,將鍵盤掃描處理過程化分成三個(gè)狀態(tài),每個(gè)狀態(tài)的功能為:
√狀態(tài)0,鍵盤掃描檢測(cè)??刂芇D3-PD6,4根行線逐行輸出低電平,對(duì)鍵盤
進(jìn)行掃描檢測(cè)。一旦檢測(cè)到有鍵按下(key_value),立即停止鍵盤的掃描,狀態(tài)轉(zhuǎn)換到狀態(tài)1。注意此時(shí)變量key_value中保存著讀到的列線輸入值,而且該行線低電平的輸出是保持不變的。
√狀態(tài)1,消抖處理和鍵盤編碼。再次檢測(cè)鍵盤列線的輸入,并與狀態(tài)0時(shí)的
key_value比較,不相等則返回狀態(tài)0,實(shí)現(xiàn)了消抖處理。相等則確認(rèn)該鍵的輸入,進(jìn)行鍵盤編碼和設(shè)置函數(shù)的返回值,狀態(tài)轉(zhuǎn)化到狀態(tài)2。
√狀態(tài)2,等待按鍵釋放。控制PD3-PD6,4根行線全部輸出低電平,檢測(cè)3
根列線輸入全部為高電平(無(wú)按鍵按下)時(shí)狀態(tài)返回到狀態(tài)0。
讀者在閱讀該段程序時(shí),請(qǐng)注意key_mask、key_value、key_line的作和用它們不僅與鍵盤的硬件連接有關(guān)系,同時(shí)還要注意他們?cè)诔绦蛑惺侨绾问褂玫?,其值的保存等等?/p>
通過這個(gè)例子也可以看出,在硬件設(shè)計(jì)的過程中,也需要認(rèn)真考慮軟件的寫。比如,你也可以將4根鍵盤行線與PD0、PD2、PD3、PD6連接,列線使用PD1、PD4、PD5,從硬件的角度看是完全可以的,但會(huì)給軟件編寫造成很多麻煩。所以,一個(gè)好的嵌入式系統(tǒng)工程師必須同時(shí)具備良好的軟件設(shè)計(jì)編寫能力和硬件設(shè)計(jì)能力。
實(shí)際上read_keyboaed()還是一個(gè)比較簡(jiǎn)單的鍵盤接口函數(shù),還不能處理類似多鍵按下的識(shí)別、按鍵“連發(fā)”等功能。但當(dāng)你真正掌握了基本鍵盤接口的設(shè)計(jì)思想和方法后,就可以在這個(gè)簡(jiǎn)單的鍵盤接口函數(shù)基礎(chǔ)上,設(shè)計(jì)出功能更加完善的鍵盤系統(tǒng)了。
(注1)當(dāng)AVR的I/O口處于輸入方式工作時(shí),其對(duì)應(yīng)的PINx就是外部引腳上的實(shí)際電平。為了防止讀入PINx時(shí)數(shù)據(jù)的不穩(wěn)定和不確定,(例如在讀的期間,正好引腳電平發(fā)生改變),AVR的I/O輸入端到總線之間加入一個(gè)同步鎖存器,用以保證讀入數(shù)據(jù)的穩(wěn)定和確定。同步鎖存器在系統(tǒng)I/O時(shí)鐘的作用下,經(jīng)過1/2-3/2個(gè)系統(tǒng)時(shí)鐘周期,將引腳電平鎖定,提供MCU讀取。也就是說(shuō)外部引腳的電平變化要經(jīng)過1/2-3/2個(gè)時(shí)鐘周期才能真正的被讀到,見圖9-9。
因此,當(dāng)編寫程序讀取AVR的I/O口PINx電平值時(shí)應(yīng)注意:
當(dāng)I/O口從輸出方式改成輸入方式后,應(yīng)延時(shí)一個(gè)CLK再讀。
當(dāng)I/O外部引腳電平改變后,也要延時(shí)一個(gè)CLK后再讀取。
在本例的鍵盤掃描程序中,根據(jù)掃描條件,首先改變行線輸出的電平,如果按鍵按下的話,那么對(duì)應(yīng)點(diǎn)的列線(輸入口)電平也馬上改變了,此時(shí)需要延時(shí)一個(gè)CLK后讀列線的輸入電平值才是正確的。程序中采用輸出2次相同的行電平的方式,第2次輸出的實(shí)際作用是起到延時(shí)的作用(其實(shí)相當(dāng)于2個(gè)NOP)。當(dāng)然,也可以輸出1次行電平,在讀I/O口時(shí)采用讀2次的方式,只要滿足規(guī)定的延時(shí)時(shí)間就可以的。
矩陣鍵盤的原理
其中矩陣鍵盤是一種比較常用的方法。矩陣鍵盤的電路圖如下:
矩陣式鍵盤由行線和列線組成,按鍵位于行、列的交叉點(diǎn)上。當(dāng)鍵被按下時(shí),其交點(diǎn)的行線和列線接通,相應(yīng)的行線或列線上的電平發(fā)生變化,單片機(jī)通過檢測(cè)行或列線上的電平變化可以確定哪個(gè)按鍵被按下。
矩陣鍵盤不僅在連接上比單獨(dú)式按鍵復(fù)雜,它的按鍵識(shí)別方法也比單獨(dú)式按鍵復(fù)雜。矩陣鍵盤的檢測(cè)方法有多種,常見的有:逐點(diǎn)掃描法、逐行掃描法、全局掃描法。在本實(shí)例中我們采用逐行掃描法來(lái)實(shí)現(xiàn)按鍵檢測(cè),其中PD0-PD3作為列線,PD4-PD7作為行線。識(shí)別過程如下:
1、判斷鍵盤中是否有鍵按下。設(shè)置所有行線為輸出口,并輸出低電平;設(shè)置列線為輸入口,讀取列線上的電平狀態(tài),只要有一列的電平為低,就表示有按鍵按下,并且被按下的鍵位于電平為低的列線與4跟行線相交叉的4個(gè)按鍵中,若所有列線都為高電平,表示沒有按鍵按下;
2、判斷被按下按鍵所在的位置。在確認(rèn)有鍵按下后(進(jìn)行按鍵消抖處理后),接下來(lái)就是確定具體哪個(gè)案件被按下,方法是:依次將每根行線設(shè)置為輸出口,并輸出低電平(同時(shí)剩余行線輸出高電平),然后逐列檢查每根列線的電平狀態(tài),若某列為低電平,則該列線與設(shè)置為輸出低電平的行線交叉處的按鍵就是被按下的按鍵。
3、按鍵位置確定后,接下來(lái)就要給矩陣鍵盤中的每個(gè)按鍵進(jìn)行編號(hào),也就是進(jìn)行按鍵編碼,程序設(shè)計(jì)中常用計(jì)算法和查表法兩種方式對(duì)按鍵進(jìn)行編碼,本實(shí)例采用計(jì)算法編碼。
從上面的電路圖中我們可以看到,鍵盤的所有行線和列線都接了上拉電阻,這是為了確保在沒有按鍵按下的時(shí)候,I/O口的電平狀態(tài)始終為高電平,從而消除外界干擾。
對(duì)于AVR單片機(jī)來(lái)說(shuō),我們已經(jīng)知道在I/O口輸入狀態(tài)下,可以使能其內(nèi)部上拉電阻,所以上面電路圖中連接4根列線的上拉電阻可以不用,直接使能內(nèi)部上拉電阻即可。
評(píng)論
查看更多