單個按鍵實現單擊、雙擊、長按的實現


直接貼上源碼和測試例程,附帶的都有中文注釋不多做解釋。

底層驅動:

  1 #define key_state_0 0
  2 #define key_state_1 1
  3 #define key_state_2 2
  4 #define key_state_3 3
  5  
  6 #define key_no         0
  7 #define key_click    1
  8 #define key_double    2
  9 #define key_long    3
 10  
 11 #define key_input    P30
 12 /***************************************************************************
 13 程序功能:一個按鍵的單擊、雙擊、長按。三種按鍵方式,然后做不同的處理。   
 14 ***************************************************************************/
 15  
 16 static unsigned char key_driver(void)
 17 {
 18     static unsigned char key_state_buffer1 = key_state_0;
 19     static unsigned char key_timer_cnt1 = 0;
 20     unsigned char key_return = key_no;
 21     unsigned char key;
 22     
 23     key = key_input;  //read the I/O states
 24     
 25     switch(key_state_buffer1)
 26     {
 27         case key_state_0:
 28             if(key == 0)
 29                 key_state_buffer1 = key_state_1; 
 30                 //按鍵被按下,狀態轉換到按鍵消抖和確認狀態//
 31             break;
 32             
 33         case key_state_1:
 34             if(key == 0)
 35             {
 36                 key_timer_cnt1 = 0;
 37                 key_state_buffer1 = key_state_2;
 38                 //按鍵仍然處於按下狀態
 39                 //消抖完成,key_timer開始准備計時
 40                 //狀態切換到按下時間計時狀態
 41             }
 42             else
 43                 key_state_buffer1 = key_state_0;
 44                 //按鍵已經抬起,回到按鍵初始狀態
 45             break;  //完成軟件消抖
 46             
 47         case key_state_2:
 48             if(key == 1) 
 49             {
 50                 key_return = key_click;  //按鍵抬起,產生一次click操作
 51                 key_state_buffer1 = key_state_0;  //轉換到按鍵初始狀態
 52             }
 53             else if(++key_timer_cnt1 >= 100)  //按鍵繼續按下,計時超過1000ms
 54             {
 55                 key_return = key_long;  //送回長按事件
 56                 key_state_buffer1 = key_state_3;  //轉換到等待按鍵釋放狀態
 57             }
 58             break;
 59             
 60         case key_state_3:  //等待按鍵釋放
 61             if(key == 1)  //按鍵釋放
 62                 key_state_buffer1 = key_state_0;  //切回按鍵初始狀態
 63             break;
 64     }
 65     return key_return;
 66 }
 67  
 68 /***************************************************************************
 69 函數功能:中層按鍵處理函數,調用底層函數一次,處理雙擊事件的判斷,
 70                                         返回上層正確的無鍵、單擊、雙擊、長按四種狀態
 71 本函數由上層循環調用,間隔10ms
 72 ***************************************************************************/
 73 unsigned char key_read(void)
 74 {
 75     static unsigned char key_state_buffer2 = key_state_0;
 76     static unsigned char key_timer_cnt2 = 0;
 77     unsigned char key_return = key_no;
 78     unsigned char key;
 79     
 80     key = key_driver();
 81     
 82     switch(key_state_buffer2)
 83     {
 84         case key_state_0:
 85             if(key == key_click)
 86             {
 87                 key_timer_cnt2 = 0;  //第一次單擊,不返回,到下個狀態判斷是否會出現雙擊
 88                 key_state_buffer2 = key_state_1;
 89             }
 90             else 
 91                 key_return = key;  //對於無鍵、長按,返回原事件
 92             break;
 93             
 94         case key_state_1:
 95             if(key == key_click)  //又一次單擊,時間間隔小於500ms
 96             {
 97                 key_return = key_double;  //返回雙擊事件,回到初始狀態
 98                 key_state_buffer2 = key_state_0;
 99             }
100             else if(++key_timer_cnt2 >= 50)
101             {
102                 //這里500ms內肯定讀到的都是無鍵事件,因為長按大於1000ms
103                 //在1s前底層返回的都是無鍵
104                                                         
105                 key_return = key_click;  //500ms內沒有再次出現單擊事件,返回單擊事件
106                 key_state_buffer2 = key_state_0;  //返回初始狀態
107                             
108             }
109             break;
110     }
111     
112     return key_return;
113 }

測試例程(基於51內核)

 1 void main(void)
 2 {
 3     u8 cnt_1ms=0,cnt_100ms=0;
 4     u8 key_value = 0;
 5     u8 led_flash=0;
 6     GPIO_Configuration();
 7     P3M1 &= ~(1<<0);P3M2 &= ~(1<<0); //P30准雙向
 8     P1M1 &= ~(1<<2);P1M2 |=  (1<<2); //P12推挽
 9     
10     P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();
11     P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();
12     P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();
13     P12=0;Delay_ms(500);P12=1;Delay_ms(500);IWDG_Feed();
14     
15     enableInterrupts();
16     IWDG_Configuration();
17     while(1)
18     {
19         if(++cnt_1ms>=10)
20         {
21             cnt_1ms=0;
22             key_value = key_read();
23             if(key_value != key_no) led_flash = key_value*2;
24         }
25         if(++cnt_100ms>=100)
26         {
27             cnt_100ms=0;
28             if(led_flash)
29             {
30                 led_flash--;
31                 P12 = ~P12;
32             }
33         }
34     }
35 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM