1. 程式人生 > >EC修煉之道—按鍵的做法

EC修煉之道—按鍵的做法

在EC的各項功能中,按鍵的作用非常重要。機器上的PowerSwitch按鍵,亮度加減按鍵,聲音加減按鍵,WIFI&Bluetooth開關等,都有可能用到按鍵功能。

         按鍵的做法有兩種:一是使用中斷的方式;二是使用輪循GPIO的電平狀態來做按鍵功能。這篇文章的重點在於介紹輪循的方式,因為第一種方式讓我吃了不少苦頭,現在我都一般不會採用它。

1 中斷方式

         這是做按鍵功能的正統方式,做的時候一板一眼,上學讀書的時候也是這麼做的。分為以下幾個步驟:第一步,想使用哪個GPIO做按鍵,就使能相應GPIO的中斷,並設定相應的中斷方式,即電平或邊沿觸發;第二步,在中斷函式中,關中斷清中斷標誌並延時去抖,然後判斷電平狀態,如果無誤,則呼叫該按鍵的功能函式;第三步,開中斷,迎接下一步的中斷。

2 輪循GPIO電平狀態

         這是我大比較喜歡的方式,當我一接觸到這種方式時,便將以前的程式碼全改成這種方式。甚至連其它的8051微控制器程式,我都這樣做。

2.1 優勢

         這種方法相對第1種方式,佔據比較大的優勢。首先,它不會用程式延時,所以不會拖慢其他模組的功能;其次,程式設計相對簡單,只要邏輯層做起來,留出一個數據陣列給OEM層來使用,填一個數組總比寫程式失誤率要小得多;再者,有很多按鍵功能需要repeat,用中斷的方式沒法準確控制repeat的時間,而且延時得太多,用輪循的方式可以輕而易舉完美地做到這個功能(我自己加的)。

2.2  具體實現方式       

我們來看一下OEM介面:

typedefvolatile struct _EVENT_DESCRIPTOR

{

    BYTE PortPin;        //使用的GPI

    BYTE Bounce;     // 去抖延時時間

}EVENT_DESCRIPTOR;

static constEVENT_DESCRIPTOR Events_Table[] =

{

    {PWRBTN_IN, 10},         //PowerSwitch

    {VOLUME_UP, 10},         //聲音加

                   {VOLUME_DOWN, 10},     //聲音減

};

簽了NDA,就要為別人保密。掃描按鍵的程式碼就不貼了,畫張流程圖吧。

流程圖:

2.3 加repeat功能

         Vendor畢竟不是OEM,並不知道OEM廠商的具體需求,所以沒有加入repeat功能,但基於vendor的codebase,加repeat功能並不困難。

         首先改變結構體如下:

typedefvolatile struct _EVENT_DESCRIPTOR

{

    BYTE PortPin;        //使用的GPI

    BYTE Bounce;     // 去抖延時時間

                   BYTE DelayToRepeat;      //開始Repeat的時間

                   BYTE PeroidRepeat;                  //Repeat的間隔時間

}EVENT_DESCRIPTOR;

static constEVENT_DESCRIPTOR Events_Table[] =

{

    {PWRBTN_IN, 10,0,0},         //PowerSwitch

    {VOLUME_UP, 10,50,10},              //聲音加

                   {VOLUME_DOWN, 10,50,10},   //聲音減

};

然後再改變一下掃描按鍵的程式碼,需要加三部分:一,在按鍵電平狀態不一致時,除了儲存上一電平外,還要清除一下儲存DelayToRepeat和PeroidRepeat值的計數陣列;二,在去拌時間結束後,要判斷當前狀態是否為ACTIVE和是否需要Repeat功能,如果這兩條件滿足,則將DelayToRepeat賦值給計數陣列;三,計數陣列計數結束後,執行按鍵功能函式,並將PeroidRepeat值重新賦給計數陣列。