如何用最少的IO驅動更多的按鍵

本文以循序漸進的思路,引導大家思考如何用最少的IO驅動更多的按鍵,並依次給出5種方案原理圖提供參考。

問題的引入

在實際項目中我們經常會遇到有按鍵輸入的需求,但有的時候為了節省資源成本,我們都會選擇在不增加硬件的情況下使用最少的控制器IO驅動更多的按鍵,那麼具體是怎麼做的呢,下面我們就以用5個IO引腳為例,講下怎麼設計可以實現更多的按鍵?共有5種設計思路,下面依次介紹。

思路一

首先通常想到的可能是下面這樣的設計:

上圖形式的按鍵就是我們通常說的行列式按鍵,它的驅動思路是這樣的:

對IO1、2、3配置為推輓輸出,依次只讓其中一個輸出為0其他輸出為1。

對IO4、5進行讀操作,根據讀出的結果判斷哪個按鍵按下。

例如:配置IO1、2、3為011,讀IO4、5,若IO4為0則SW14按下,若IO5為0則SW15按下;

依次的配置IO1、2、3為101,讀IO4、5,若IO4為0則SW24按下,若IO5為0則SW25按下;

依次的配置IO1、2、3為110,讀IO4、5,若IO4為0則SW34按下,若IO5為0則SW35按下;

思路二

但是我們在不知道行列式按鍵之前我們肯定是依次將IO口接一個按鍵到GND或者到VCC,然後去讀IO口去判斷哪個按鍵按下,這也是最簡單的方法,但是很浪費IO口,下面這種就結合了這種簡單方法和行列式的思路,實現了又多增加3個按鍵,如下圖:

如何用最少的IO驅動更多的按鍵

裡我們對按鍵識別路是先依次讀IO1、2、3的電平來識別S1、2、3,哪個按鍵按下,其後的流程和思路一是一樣的,這樣就可以識別11個按鍵了。

思路三

按照掃描的思想,某一時刻設置一個IO口為0,其他IO口讀,如果有IO口為,讀到0有對應按鍵按下。比如IO1為0,然後讀到IO5也為0,那麼K15就是按下的。對照這樣的思路,我們可以有下面的設計:

如何用最少的IO驅動更多的按鍵

個電路按鍵識別思路是這樣的:

  1. 只配置IO1為0,其他IO讀,若IO5讀到0,則K15按下,若IO4讀到0,則K14按下,依次識別K13,K12;
  2. 只配置IO2為0,其他IO讀,若IO5讀到0,則K25按下,若IO4讀到0,則K24按下,依次識別K23;
  3. 只配置IO3為0,其他IO讀,若IO5讀到0,則K35按下,若IO4讀到0,則K34按下;
  4. 只配置IO4為0,其他IO讀,若IO5讀到0,則K45按下;

思路四

對於思路3我們發現,如果只配置IO5為0,其他IO讀,若IO1讀到0,則K15按下,若IO2讀到0,則K25按下,依次可識別K35和K45。這樣就存在重複,那麼有麼有好的方法,解決這樣的重複呢?我們發現,若配置IO1為0,K15按下,電流流向IO1的,若配置IO5為0,同樣K15按下,電流是流向IO5的。這樣我們就可以通過區分電流的流向來避免重複。於是就有了下圖的設計:

如何用最少的IO驅動更多的按鍵

這樣可以避免重複,IO5為0時,按K15,IO1是讀不到0的。那麼怎樣設計,IO5為0時對應一個按鍵按下IO1為0呢?如是就有人想到下面的設計:

如何用最少的IO驅動更多的按鍵

這個路按鍵識別思路是這樣的:

  1. 只配置IO1為0,其他IO讀,若IO5讀到0,則K51按下,若IO4讀到0,則K41按下,依次識別K31,K21;
  2. 只配置IO2為0,其他IO讀,若IO5讀到0,則K52按下,若IO4讀到0,則K42按下,依次識別K32,K21';
  3. 只配置IO3為0,其他IO讀,若IO5讀到0,則K53按下,若IO4讀到0,則K43按下,依次識別K32',K31';
  4. 只配置IO4為0,其他IO讀,若IO5讀到0,則K54按下,若IO4讀到0,則K43'按下,依次識別K42',K41';
  5. 只配置IO5為0,其他IO讀,若IO4讀到0,則K54'按下,若IO3讀到0,則K53'按下,依次識別K52',K51'。

思路五

很多人可能認為思路四已經識別20個按鍵了,但是真的就沒有其他方法了嗎?不要忘了,我們還沒有將思路二你介紹的那種最簡單的方法結合進去,於是又可以多5個按鍵,如下圖:

如何用最少的IO驅動更多的按鍵

這樣我可以先識別K01、K02、K03、K04、K05,若沒有按鍵按下,然後再和思路四的流程一樣去識別其他按鍵。但這樣存在一個問題,如果IO1配置為0,IO5讀到0,那麼怎麼知道是K51按下還是K05按下呢,這裡只需要在程序裡做下判斷,先判斷下是不是K05按下,若不是就是K51,因為按鍵K01、K02、K03、K04、K05在5個IO口都為讀取的情況下,就可以識別,不需要掃描識別處理,相當於這5個按鍵優先級高與其他按鍵。

總結

綜合上述,5個IO口最多可以識別25個按鍵,思路五程序上處理比較麻煩,若實際中只按思路四設計,也可識別20個按鍵,那麼如果有N個IO口可識別多少按鍵呢?這裡給出如下公式:

假設有N個IO口按照思路三可以識別N*(N-1)/2個;

按照思路四可識別N*(N-1)個;

按照思路5可以識別N*(N-1)+N個。

從上面我們發現用思路四的方法,我們可以用5個IO口實現20個按鍵的功能,也足以滿足市場上的4*4=16個矩陣按鍵的需求,這也是我為什麼用5個IO口介紹這篇文章的原因。

最後再說下,如果實際設計時,還是按思路四設計好,軟件也沒那麼麻煩。如果是你的話你會選擇哪種方法呢?你還有沒有其他的設計方法呢?

下面就再介紹另外一種運用組合邏輯的思想設計的一個按鍵識別的方法。

用3個IO口掃描識別16個按鍵的方法

話不多說,先看原理圖,如下:

如何用最少的IO驅動更多的按鍵

從圖中可以看出,使用了12個二極管和16個按鍵,此方法識別按鍵過程如下:

  1. 先將3個IO口都配置成1,相當於上拉輸入,然後讀取IO的值,只要3個IO的值為非全1,就說明按鍵BT01~BT07有按鍵按下,如果讀取值全為1,則進行下一步掃描識別。
  2. 依次的設置其中一個IO口為0,其他兩個IO口讀,根據要讀的兩個IO口的狀態識別按鍵BT08~BT16,比如:

設置IO01、02、03依次為011,然後讀IO02、03,若IO02讀為0,則BT11按下,若IO03為0,則BT13按下,若IO02、03都為0則BT16按下,如此識別其他剩餘按鍵,但此處若BT11和BT13都按下,會誤以為是BT16按下。

從上面介紹的可以看出,這種方法運用了邏輯組合的思路,此方法只要用3個IO可以掃描識別16個按鍵,但是對於有些按鍵同時按下,會有錯誤的識別結果。而且使用了較多的二極管,如果用4個IO口的話,使用的二極管的成本都可以外接一個專門的按鍵識別芯片了,不能實現組合按鍵功能,也是此設計的弊端,不建議使用。

2個IO檢測6個按鍵的方法

單片機IO口如果識別更多的按鍵,簡單的方法就是通過控制按鍵按下,識別電流的流向。這說可能不是很理解,下面就來介紹下,如下圖按鍵識別電路:

如何用最少的IO驅動更多的按鍵

按鍵S1按下,電流是從R1流向GND的,S2按下是從R2流向GND,S3按下是從R1和R2共同流向GND。

S4按下是從IO1流向IO2,也可以從IO2流向IO1,S5按下是從IO1流向IO2,S6按下是從IO2流向IO1。按鍵按下和電流流向關係如下:

如何用最少的IO驅動更多的按鍵


那麼這6個按鍵單片機要怎麼識別呢,下面就說下識別思路流程:

1. 先配置IO1和IO2都為1,然後讀IO1和IO2,若讀到IO1為0,那麼S1按下,若讀到IO2為0,那麼S2按下,若讀到IO1和IO2都為0,那麼S3按下,若IO1和IO2都沒讀到0,那麼進行下一步;

2. 配置IO1為0,IO2為1,讀IO2,若讀IO2為1,進入下一步,若IO2讀為0,那麼可以判斷是S4或S6按下,然後再配置IO2為0,IO1為1,讀IO1,若IO1讀為0,那麼就是S4按下,若IO1讀為1就是S6按下了。

3. 配置IO2為0,IO1為1,讀IO1,若IO1讀為0,那麼就是S5按下了。

將上面的電路圖再精簡下就是下面的圖形了,是不是很有美感,下面的電路還比上面的那個電路省2個二極管哦。

如何用最少的IO驅動更多的按鍵

2個IO2個二極管識別6個按鍵

以後有2個IO,識別按鍵就用此方法吧!

歡迎評論交流。也歡迎大家關注我的

頭條號:單片機嵌入式愛好者。會有源源不斷的乾貨分享,能真正快速幫大家解決實際工作中遇到的問題哦!


分享到:


相關文章: