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


    直接贴上源码和测试例程,附带的都有中文注释不多做解释。

    底层驱动:

      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 }
  • 相关阅读:
    1059. C语言竞赛(20)
    1057. 数零壹(20)
    1056. 组合数的和(15)
    1054. 求平均值 (20)
    1052. 卖个萌 (20)
    1053. 住房空置率 (20)
    第五周课后作业02(动手动脑)
    课堂动手动脑
    课后作业
    课堂测试动手动脑
  • 原文地址:https://www.cnblogs.com/huangyangquan/p/10619544.html
Copyright © 2020-2023  润新知