矩陣鍵盤的使用在單品機的學習當中十分廣泛,可是對於許多新手,包括本人有時也是搞不明白,昨天晚上和今天早上的思考和同行們的討論,終於有了點頭緒,所以想記錄下讀取鍵盤的思路。
在單片機的學習版中,矩陣鍵盤通常如下圖設計:
下面就以按下S16鍵來講解其思路:
首先:
P3的高位P3.4~P3.7輸出爲0,低位P3.0~P3.3輸出爲1;即P3=0x0F,當按下S16鍵後(有消抖動過程),P3.3的值爲0,則P3的值更新爲0x07;
其次:
P3的高位P3.4~P3.7輸出爲1,低位P3.0~P3.3輸出爲0;即P3=0xF0,當按下S16鍵後(有消抖動過程),P3.4的值爲0,則P3的值更新爲0xE0;
最後將兩個值相加得P3=0xE7;
在keyscan()函數(假設我們的鍵盤掃描程序爲unsigned char keyscan())返回其鍵盤的值供後續的程序調用,通常會有一個switch塊根據其返回值來確定輸出的是哪一個數值。
下面提供一段KeilC51語言的代碼來解釋一下:
- <SPAN style="FONT-SIZE: 18px">/*------------------------------------------------
- 鍵盤掃描程序
- ------------------------------------------------*/
- uchar keyscan( void ) //鍵盤掃描函數,使用行列反轉掃描法
- {
- uchar cord_h,cord_l;//行列值中間變量
- P3 = 0x0f; //行線輸出全爲0
- cord_h = P3 & 0x0f; //讀入列線值
- if( cord_h != 0x0f ) //先檢測有無按鍵按下
- {
- delay( 100 ); //去抖
- if( cord_h != 0x0f )
- {
- cord_h = P3 & 0x0f; //讀入列線值
- P3 = cord_h | 0xf0; //輸出當前列線值
- cord_l = P3 & 0xf0; //讀入行線值
- return( cord_h + cord_l );//鍵盤最後組合碼值
- }
- }
- return( 0xff ); //返回該值
- }
- </SPAN>
/*------------------------------------------------
鍵盤掃描程序
------------------------------------------------*/
uchar keyscan( void ) //鍵盤掃描函數,使用行列反轉掃描法
{
uchar cord_h,cord_l;//行列值中間變量
P3 = 0x0f; //行線輸出全爲0
cord_h = P3 & 0x0f; //讀入列線值
if( cord_h != 0x0f ) //先檢測有無按鍵按下
{
delay( 100 ); //去抖
if( cord_h != 0x0f )
{
cord_h = P3 & 0x0f; //讀入列線值
P3 = cord_h | 0xf0; //輸出當前列線值
cord_l = P3 & 0xf0; //讀入行線值
return( cord_h + cord_l );//鍵盤最後組合碼值
}
}
return( 0xff ); //返回該值
}
首先把P3的口賦值爲0x0f,同時把P3和0x0f賦值給cord_h(行的數值),倘若有按鍵按下,那麼P3的值就會改變,隨後cord_h的只也會隨之變化,經過消抖之後記錄cord_h的值,
即cord_h = P3 & 0x0f;
(若以S16爲例,那麼P3.3的值變爲0,所以cord_h的值就會變爲0x07;)
接下來:P3 = cord_h | 0xf0;
意在不改變P3的第四位,把P3的高四位賦爲高電平,那麼P3=0x0f7;
到了關鍵的一步:
cord_l = P3 & 0xf0;我當初以爲cord_l=0xf0呢,結果就和程序運行的不一樣嘍,最後還是問了我的同行(非常感謝劉偉同志!指點迷津!),其實在第二個if語言內,S16已經被按下了的,所以P3的值立刻就變爲0x0e的了,以至於cord_l=0x0e,最後返回行和列的和return( cord_h + cord_l );(0xe7)。這纔是最終對的結果,各位看官懂了嗎?O(∩_∩)O哈哈~