在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(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(遙控器)
            按按鍵功能分:有短按鍵,長按鍵,連續(xù)按鍵。打個(gè)比方,遙控電視機(jī),按一下音量鍵,音量增加1,這個(gè)就是短按鍵。按住音量鍵不放,音量連續(xù)加,這個(gè)就是連續(xù)按鍵。按住一個(gè)按鍵5s,系統(tǒng)會(huì)復(fù)位,這個(gè)是長按鍵。

            本文引用地址:http://www.biyoush.com/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.  }  

             

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

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

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

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

            3.  */

            4. #define BUTTON_FILTER_TIME         5

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

            6. /*

            7.         每個(gè)按鍵對應(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;                /* 長按計(jì)數(shù)器 */

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

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

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

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

            21.         unsigned char  KeyCodeLong;        /* 按鍵長按的鍵值代碼, 0表示不檢測長按 */

            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,                        /* 按鍵鍵長按 */

            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按鍵變量,支持按下、彈起、長按 */

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

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

            46.         s_Powerkey.LongTime = BUTTON_LONG_TIME;                        /* 長按時(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. *        功能說明: 檢測一個(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. //功能說明: 檢測所有按鍵。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)遙控器按鍵的長短按功能和連續(xù)按鍵功能。代碼裁剪過,大家根據(jù)實(shí)際需要改動(dòng)。其實(shí)AD按鍵,通過AD采樣獲得按鍵值之后,可以采取如下面的一樣方法處理,提一個(gè)函數(shù)接口即可

             

            1. typedefstruct

            2. {  

            3.   unsigned char count;//

            4.   unsigned char LongkeyFlag;/*是否長按鍵,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 按鍵處理

            評論


            相關(guān)推薦

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

            關(guān)閉