中文字幕 另类精品,亚洲欧美一区二区蜜桃,日本在线精品视频免费,孩交精品乱子片免费

<sup id="3hn2b"></sup>

    1. <sub id="3hn2b"><ol id="3hn2b"></ol></sub><legend id="3hn2b"></legend>

      1. <xmp id="3hn2b"></xmp>

      2. 新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > MCU實(shí)戰(zhàn)經(jīng)驗(yàn):多種的按鍵處理

        MCU實(shí)戰(zhàn)經(jīng)驗(yàn):多種的按鍵處理

        作者: 時(shí)間:2016-06-30 來源:網(wǎng)絡(luò) 收藏

        按鍵通常有:IO口按鍵(BUTTON),AD按鍵(通過AD采樣電壓),IR(遙控器)
        按按鍵功能分:有短按鍵,長(zhǎng)按鍵,連續(xù)按鍵。打個(gè)比方,遙控電視機(jī),按一下音量鍵,音量增加1,這個(gè)就是短按鍵。按住音量鍵不放,音量連續(xù)加,這個(gè)就是連續(xù)按鍵。按住一個(gè)按鍵5s,系統(tǒng)會(huì)復(fù)位,這個(gè)是長(zhǎng)按鍵。

        本文引用地址:http://www.antipu.com.cn/article/201606/293391.htm

        1、IO口按鍵,就是我們比較常見的一個(gè)IO接一個(gè)按鍵,或者是一個(gè)矩陣鍵盤。很多新人的處理方法可能是采樣延時(shí)的方法,當(dāng)年我也是這樣的,如下

        1. if(GETIO==low)  

        2.  {   

        3.    delay_10ms()  

        4. if(GETIO==low)  

        5.    {  

        6. //得到按鍵值

        7.    }  

        8.  }  

         

        這種方法雖然簡(jiǎn)單,但是有很大弊端。首先 Delay浪費(fèi)很多時(shí)間,影響系統(tǒng)。第二,無法判斷長(zhǎng)短按鍵,連續(xù)按鍵。第三,如果這個(gè)按鍵是開關(guān)機(jī)按鍵系統(tǒng)在低功耗狀態(tài)下,需要中斷喚醒,這種方法比較容易出問題,如STM8S系列的 halt 模式。

        所以我們一般在產(chǎn)品開發(fā)的過程中,采用掃描的方法,就是每隔10ms 去檢測(cè)IO的狀態(tài),看是否有按鍵,然后去抖動(dòng),判斷按鍵功能。參考代碼如下,這段代碼是之前在一個(gè)論壇看到的比我自己寫的更加優(yōu)秀,所以拿出來和大家分享一下,也順便感謝一下作者。這段代碼,容易修改,可以根據(jù)自己的時(shí)間需要,進(jìn)行長(zhǎng)短按鍵,連續(xù)按鍵,還有組合按鍵的判斷。

        1. /* 按鍵濾波時(shí)間50ms, 單位10ms

        2.  *只有連續(xù)檢測(cè)到50ms狀態(tài)不變才認(rèn)為有效,包括彈起和按下兩種事件

        3.  */

        4. #define BUTTON_FILTER_TIME         5

        5. #define BUTTON_LONG_TIME         300                /* 持續(xù)1秒,認(rèn)為長(zhǎng)按事件 */

        6. /*

        7.         每個(gè)按鍵對(duì)應(yīng)1個(gè)全局的結(jié)構(gòu)體變量。

        8.         其成員變量是實(shí)現(xiàn)濾波和多種按鍵狀態(tài)所必須的

        9. */

        10. typedefstruct

        11. {  

        12. /* 下面是一個(gè)函數(shù)指針,指向判斷按鍵手否按下的函數(shù) */

        13.         unsigned char  (*IsKeyDownFunc)(void); /* 按鍵按下的判斷函數(shù),1表示按下 */

        14.         unsigned char  Count;                        /* 濾波器計(jì)數(shù)器 */

        15.         unsigned char  FilterTime;                /* 濾波時(shí)間(最大255,表示2550ms) */

        16.         unsigned short LongCount;                /* 長(zhǎng)按計(jì)數(shù)器 */

        17.         unsigned short LongTime;                /* 按鍵按下持續(xù)時(shí)間, 0表示不檢測(cè)長(zhǎng)按 */

        18.         unsigned char   State;                        /* 按鍵當(dāng)前狀態(tài)(按下還是彈起) */

        19.         unsigned char  KeyCodeUp;                /* 按鍵彈起的鍵值代碼, 0表示不檢測(cè)按鍵彈起 */

        20.         unsigned char  KeyCodeDown;        /* 按鍵按下的鍵值代碼, 0表示不檢測(cè)按鍵按下 */

        21.         unsigned char  KeyCodeLong;        /* 按鍵長(zhǎng)按的鍵值代碼, 0表示不檢測(cè)長(zhǎng)按 */

        22.         unsigned char  RepeatSpeed;        /* 連續(xù)按鍵周期 */

        23.         unsigned char  RepeatCount;        /* 連續(xù)按鍵計(jì)數(shù)器 */

        24. }BUTTON_T;  

        25. typedefenum

        26. {  

        27.         KEY_NONE = 0,                        /* 0 表示按鍵事件 */

        28.         KEY_DOWN_Power,                        /* 按鍵鍵按下 */

        29.         KEY_UP_Power,                        /* 按鍵鍵彈起 */

        30.         KEY_LONG_Power,                        /* 按鍵鍵長(zhǎng)按 */

        31.         KEY_DOWN_Power_TAMPER        /* 組合鍵,Power鍵和WAKEUP鍵同時(shí)按下 */

        32. }KEY_ENUM;  

        33. BUTTON_T s_Powerkey;                  

        34. //是否有按鍵按下接口函數(shù)

        35. unsigned char  IsKeyDownUser(void)                   

        36. {if (0==GPIO_ReadInputPin(POWER_KEY_PORT, POWER_KEY_PIN) ) return 1;return 0;}  

        37. void  PanakeyHard_Init(void)  

        38. {  

        39.    GPIO_Init (POWER_KEY_PORT, POWER_KEY_PIN, GPIO_MODE_IN_FL_NO_IT);//power key

        40. }  

        41. void  PanakeyVar_Init(void)  

        42. {  

        43. /* 初始化USER按鍵變量,支持按下、彈起、長(zhǎng)按 */

        44.         s_Powerkey.IsKeyDownFunc = IsKeyDownUser;                /* 判斷按鍵按下的函數(shù) */

        45.         s_Powerkey.FilterTime = BUTTON_FILTER_TIME;                /* 按鍵濾波時(shí)間 */

        46.         s_Powerkey.LongTime = BUTTON_LONG_TIME;                        /* 長(zhǎng)按時(shí)間 */

        47.         s_Powerkey.Count = s_Powerkey.FilterTime / 2;                /* 計(jì)數(shù)器設(shè)置為濾波時(shí)間的一半 */

        48.         s_Powerkey.State = 0;                                                        /* 按鍵缺省狀態(tài),0為未按下 */

        49.         s_Powerkey.KeyCodeDown = KEY_DOWN_Power;                        /* 按鍵按下的鍵值代碼 */

        50.         s_Powerkey.KeyCodeUp =KEY_UP_Power;                                /* 按鍵彈起的鍵值代碼 */

        51.         s_Powerkey.KeyCodeLong = KEY_LONG_Power;                        /* 按鍵被持續(xù)按下的鍵值代碼 */

        52.         s_Powerkey.RepeatSpeed = 0;                                                /* 按鍵連發(fā)的速度,0表示不支持連發(fā) */

        53.         s_Powerkey.RepeatCount = 0;                                                /* 連發(fā)計(jì)數(shù)器 */

        54. }  

        55. void Panakey_Init(void)  

        56. {  

        57.         PanakeyHard_Init();                /* 初始化按鍵變量 */

        58.         PanakeyVar_Init();                /* 初始化按鍵硬件 */

        59. }  

        60. /*

        61. *********************************************************************************************************

        62. *        函 數(shù) 名: bsp_DetectButton

        63. *        功能說明: 檢測(cè)一個(gè)按鍵。非阻塞狀態(tài),必須被周期性的調(diào)用。

        64. *        形    參:按鍵結(jié)構(gòu)變量指針

        65. *        返 回 值: 無

        66. *********************************************************************************************************

        67. */

        68. void Button_Detect(BUTTON_T *_pBtn)  

        69. {  

        70. if (_pBtn->IsKeyDownFunc())  

        71.         {  

        72. if (_pBtn->Count < _pBtn->FilterTime)  

        73.                 {  

        74.                         _pBtn->Count = _pBtn->FilterTime;  

        75.                 }  

        76. elseif(_pBtn->Count < 2 * _pBtn->FilterTime)  

        77.                 {  

        78.                         _pBtn->Count++;  

        79.                 }  

        80. else

        81.                 {  

        82. if (_pBtn->State == 0)  

        83.                         {  

        84.                                 _pBtn->State = 1;  

        85. /* 發(fā)送按鈕按下的消息 */

        86. if (_pBtn->KeyCodeDown > 0)  

        87.                                 {  

        88. /* 鍵值放入按鍵FIFO */

        89.                                         Pannelkey_Put(_pBtn->KeyCodeDown);// 記錄按鍵按下標(biāo)志,等待釋放

        90.                                 }  

        91.                         }  

        92. if (_pBtn->LongTime > 0)  

        93.                         {  

        94. if (_pBtn->LongCount < _pBtn->LongTime)  

        95.                                 {  

        96. /* 發(fā)送按鈕持續(xù)按下的消息 */

        97. if (++_pBtn->LongCount == _pBtn->LongTime)  

        98.                                         {  

        99. /* 鍵值放入按鍵FIFO */

        100.                                                 Pannelkey_Put(_pBtn->KeyCodeLong);          

        101.                                         }  

        102.                                 }  

        103. else

        104.                                 {  

        105. if (_pBtn->RepeatSpeed > 0)  

        106.                                         {  

        107. if (++_pBtn->RepeatCount >= _pBtn->RepeatSpeed)  

        108.                                                 {  

        109.                                                         _pBtn->RepeatCount = 0;  

        110. /* 常按鍵后,每隔10ms發(fā)送1個(gè)按鍵 */

        111.                                                         Pannelkey_Put(_pBtn->KeyCodeDown);          

        112.                                                 }  

        113.                                         }  

        114.                                 }  

        115.                         }  

        116.                 }  

        117.         }  

        118. else

        119.         {  

        120. if(_pBtn->Count > _pBtn->FilterTime)  

        121.                 {  

        122.                         _pBtn->Count = _pBtn->FilterTime;  

        123.                 }  

        124. elseif(_pBtn->Count != 0)  

        125.                 {  

        126.                         _pBtn->Count--;  

        127.                 }  

        128. else

        129.                 {  

        130. if (_pBtn->State == 1)  

        131.                         {  

        132.                                 _pBtn->State = 0;  

        133. /* 發(fā)送按鈕彈起的消息 */

        134. if (_pBtn->KeyCodeUp > 0) /*按鍵釋放*/

        135.                                 {  

        136. /* 鍵值放入按鍵FIFO */

        137.                                 Pannelkey_Put(_pBtn->KeyCodeUp);          

        138.                                 }  

        139.                         }  

        140.                 }  

        141.                 _pBtn->LongCount = 0;  

        142.                 _pBtn->RepeatCount = 0;  

        143.         }  

        144. }  

        145. //功能說明: 檢測(cè)所有按鍵。10MS 調(diào)用一次

        146. void Pannelkey_Polling(void)  

        147. {  

        148.         Button_Detect(&s_Powerkey);                /* USER 鍵 */

        149. }  

        150. void Pannelkey_Put(void)  

        151. {  

        152. // 定義一個(gè)隊(duì)列 放入按鍵值        

        153. }  


        2、遙控器按鍵,遙控器解碼的一般就有兩種:脈寬調(diào)制和脈沖調(diào)制,這里就不細(xì)講解碼的過程了。這里詳細(xì)解碼之后,如何處理遙控器按鍵實(shí)現(xiàn)遙控器按鍵的長(zhǎng)短按功能和連續(xù)按鍵功能。代碼裁剪過,大家根據(jù)實(shí)際需要改動(dòng)。其實(shí)AD按鍵,通過AD采樣獲得按鍵值之后,可以采取如下面的一樣方法處理,提一個(gè)函數(shù)接口即可

         

        1. typedefstruct

        2. {  

        3.   unsigned char count;//

        4.   unsigned char LongkeyFlag;/*是否長(zhǎng)按鍵,1代表是*/

        5.   unsigned char  PreKeyValue;/*按鍵值的一個(gè)備份,用于釋放按鍵值*/

        6. }ScanKeyDef;  

        7. #define SHORT_PRESS_TIME_IR                16 // 10ms 

        8. #define SERIES_PRESS_TIME_IR            10  

        9. #define LONG_PRESS_TIME_IR                    22

        10. #define KEY_RELEASE_TIME_OUT_IR     12  // 10ms 

        11. //提供5個(gè)接口函數(shù),如下。 

        12. unsigned char get_irkey(void);  

        13. unsigned char ISSeriesKey(unsigned char temp);//按鍵是否需要做連續(xù)按鍵

        14. unsigned char changeSeriesKey(unsigned char temp);//轉(zhuǎn)換連續(xù)按鍵值

        15. unsigned char ISLongKey(unsigned char temp);//按鍵是否需要做連續(xù)按鍵

        16. unsigned char changeToLongKey(unsigned char temp);//轉(zhuǎn)換連續(xù)按鍵值

        17. unsigned char KeyScan(void)   

        18. {  

        19.     unsigned char  KeyValue = KEY_NONE,  

        20.                                 KeyValueTemp = KEY_NONE;  

        21. static   unsigned char KeyReleaseTimeCount =0;  

        22.     KeyValueTemp = get_irkey();  

        23. if(KeyValueTemp != KEY_NONE)  

        24.     {  

        25.         ScanKeyDef.count++;  

        26.         KeyReleaseTimeCount =0;  

        27. if(ScanKeyDef.count < LONG_PRESS_TIME_IR )  

        28.         {  

        29.             ScanKeyDef.LongkeyFlag = 0;  

        30. if((ScanKeyDef.count == SERIES_PRESS_TIME_IR) && ISSeriesKey(KeyValueTemp)) //處理連續(xù)按鍵

        31.                 {  

        32.                     KeyValue = changeSeriesKey ( KeyValueTemp );  

        33.                     ScanKeyDef.PreKeyValue = KEY_NONE;  

        34.                 }  

        35. elseif ( ScanKeyDef.count  < SHORT_PRESS_TIME_IR )  

        36.             {  

        37.                 ScanKeyDef.PreKeyValue = KeyValueTemp;  

        38.             }  

        39. else

        40.             {  

        41.                 ScanKeyDef.PreKeyValue  = KEY_NONE; // 無效按鍵

        42.             }  

        43.         }  

        44. elseif ( ScanKeyDef.count  == LONG_PRESS_TIME_IR )  

        45.         {  

        46. if (ISLongKey(KeyValueTemp))  

        47.             {  

        48.                 {  

        49.                    ScanKeyDef.LongkeyFlag = 1;  

        50.                    KeyValue = changeToLongKey ( KeyValueTemp );  

        51.                }  

        52.           }  

        53.             ScanKeyDef.PreKeyValue = KEY_NONE;  

        54.         }  

        55. elseif (ScanKeyDef.count > LONG_PRESS_TIME_IR )  

        56.         {  

        57.             ScanKeyDef.PreKeyValue  = KEY_NONE; //無效按鍵

        58.         }  

        59.     }  

        60. else//release & no press

        61.     {  

        62.         KeyReleaseTimeCount ++;  

        63. if(KeyReleaseTimeCount >= KEY_RELEASE_TIME_OUT_IR)  

        64.         {  

        65. if ( ScanKeyDef.PreKeyValue != KEY_NONE ) //釋放按鍵值

        66.             {  

        67. if ( ScanKeyDef.LongkeyFlag == 0 )  

        68.                 {  

        69.                     KeyValue =ScanKeyDef.PreKeyValue ;  

        70.                 }  

        71.             }            

        72.             ScanKeyDef.count  = 0;  

        73.             ScanKeyDef.LongkeyFlag = 0;  

        74.            ScanKeyDef.PreKeyValue = KEY_NONE;  

        75.         }  

        76.     }  

        77. return(KeyValue);  

        78. }  



        關(guān)鍵詞: MCU 按鍵處理

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉