在系統可用的GPIO口數量有限的情況下實現按鍵板的另一個選擇就是:擴展GPIO口。擴展GPIO的方法有很多,市場上已經有很多種類的GPIO口擴展器件,但是從成本上考慮,但它們總是顯得昂貴。對於按鍵板的實現,使用基於一個移位寄存器的方法,因其低成本、方便穩定性而被廣泛使用,這里我們將討論一個基於74LS164的典型擴展IO實現按鍵板的方法。
1:硬件原理
嵌入式開發工程師必須要能看懂HW,要看懂電路,只有懂了電路是如何工作的,才可能編寫出正確的控制程序。所以,我們首先看一下74LS164(8bit移位鎖存寄存器)的工作原理。我們先給出使用74LS164實現按鍵板的原理圖,並針對這個原理圖做必要的分析解釋。
對於74LS164,除了供電之外,有兩個單向輸入端口A、B,一個CLK,一個CLR和8個單向輸出口Q0-Q7。我們關心的只是:特定的輸入會得到怎樣的輸出,就是我們應該給GPIO_1 & GPIO_2什么樣的信號,可以得到我們想要的輸出。74LS164的輸入輸出狀態見下表
也就是說:實際輸入時“A&B”,假定某一時刻A&B=1(高電平)Q0=0,在CLK的上升沿后Q0=1(原A&B的狀態) Q1=0(原Q0的狀態),就是向后移了一位。實際上可以認為:A&B->Q0->Q1->…->Q7,在CLK的每個上升沿,都會順序的向后移動一位。如果CLK信號一直為低電平,那么Q0-Q7就會之一保持其當前的狀態。這也就是所謂的移位鎖存寄存器。
根據74LS164的原理,分析一下我們的原理圖:
1:給GPIO_1(Input A & B)高電平,再給GPIO_2(CLK)送上8個脈沖信號,那么Q0-Q7均為高電平狀態。
2:給GPIO_1低電平,接着給GPIO_2一個脈沖信號,則Q0為低電平,Q1-Q7為高電平;此時讀取GPIO_3(KS_DET0),若為低電平,則表明KEY_0被按下,若為高電平,則表示KEY_0沒有動作。同理,讀取GPIO_4(KS_DET1)的狀態,可以判斷KEY_8的狀態。
3:給GPIO_1高電平,然后給GPIO_2一個脈沖信號,則Q0為高,Q1為低,Q2-Q7為高,可以判定KEY_1 & KEY_9的狀態
4:此后只需要每次給GPIO_2一個脈沖信號,就可以依次判斷其他按鍵了。
2:軟件實現
基於上面的分析,我們已經很清楚按鍵判定的原理,知道該如何控制74LS164來實現按鍵偵測。在開始軟件編程之前,一定要搞清楚我們這種實現的每一個步驟,才能確保寫出正確的代碼。下面是我的一個實現:
上述代碼提供了一個判斷與74LS164輸出端相連的開關量信號狀態的標准函數,對偵測按鍵的函數就顯得很簡短了。注意到Key_Scan()函數的實現,優先判斷無按鍵動作的情況,因為現實中的按鍵板在99%的情況下是無按鍵動作的,這樣就顯著提高了代碼效率。優秀的程序員在寫代碼的時候,不僅僅會單獨從語言特性方面來提高代碼執行效率,還很懂得根據項目的特性來提升性能。
3:討論與總結
1:使用74LS164的擴展,從嚴格意義上講,它並不能稱作擴展GPIO,但在我們的實現中,它替代了GPIO的作用。例子中的實現使用4個GPIO實現了16個按鍵。理論上推理下去,N個GPIO可以實現(N-2)*8個按鍵。
2:按鍵動作,其實就是一個開關量。只要是涉及對開關量的偵測,我們的實現都可以應用。而編程上只需要簡單的封裝,就可以想其他IO一樣,對其進行偵測
原文鏈接:https://blog.csdn.net/NutriYang/article/details/4374706