单个按键实现单击、双击、长按的实现

直接贴上源码和测试例程,附带的都有中文注释很少作解释。函数

底层驱动:测试

 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内核)spa

 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 }
相关文章
相关标签/搜索