zoukankan      html  css  js  c++  java
  • 实用按键事件检测(单击、长按)

      前断时间阅读“大佬”程序,发掘出有几个好用的,自定义的函数,此类函数巧妙使用返回值,传递参数,设置标志位、定时、赋值等功能,今晚特此来分享下。

    一、定时功能函数

    1.1   user_timer.c

    #include    "user_define.h"
    extern U16 timer1_time_cnt;
    
    static    U16 user_timer_array[USER_TIMER_AMOUNT] = {0};
    static    U16 timeout_control_array[USER_TIMER_AMOUNT] = {0};
    void user_timer_init(void)        // 数组初始化
    {
        U8 i = 0 ;
        for(i = 0; i < USER_TIMER_AMOUNT; i++){
            user_timer_array[i] = 0;
            timeout_control_array[i] = 0;
        }
    }
    
    /*********************
        function:    
            The system reference time is added to the user time array.
        parameter:
            null
        return:
            null
    *********************/
    void add_system_time(void)                  // 添加 时间 (放主循环)
    {
        U16 i = 0 ;
        U16 temp;
        
        temp = timer1_time_cnt;
        timer1_time_cnt = 0;
        
        for(i = 0; i < USER_TIMER_AMOUNT; i++)
        {
            if(user_timer_array[i] <= timeout_control_array[i])
                user_timer_array[i] += temp;
    
        }
    }
    
    /*********************
        function:    
            Clear the user time count.
        parameter:
            USER_TIMER0_CNT ...... USER_TIMERN_CNT or user typedef name
        return:
            null
    *********************/
    void clear_time_cnt(U8 time_number)        // 清除时间
    {
        if(USER_TIMER_AMOUNT > time_number)
            user_timer_array[time_number] = 0;
    }
    
    /*********************
        function:    
            time if arrived
        parameter:
            <time_number>
                USER_TIMER0_CNT ...... USER_TIMERN_CNT or user typedef name
            <time>
                check time
        return:
            null
    *********************/ 
    
    
    
    
    U8 check_time_arrive(U8 time_number, U16 time)  // 检查设定时间,是否到达
    {
        if(USER_TIMER_AMOUNT > time_number){
            timeout_control_array[time_number] = time;
            
            if(time <= user_timer_array[time_number])
                return 1;
            else
                return 0;
        }
        return 0;
    }

    1.2 user_timer.h

    //============================================
    //user timer
    //============================================
    #define    USER_TIMER_AMOUNT    5
    
    #define    KEY_TRIGGER_TIMER    0
    #define VR_TIMEOUT_TIMER    1
    #define    RANDOM_TIMER        2
    #define KEY_CONTROL_TIMER     3
    #define USER_TIMER_0        4
    
    ////============================================================
    //key
    //
    ////============================================================
    
    #define KEY_IO_INPUT    0
    #define KEY_IO_OUTPUT   1
    
    #define KEY_DEBOUNCE_TIME   8   //8MS
    #define KEY_LONG_PRESS_TIME 2300    //2s
    
    
    #define KEY_NOT_ACTION  0
    #define KEY_CLICK_ACTION   1
    #define KEY_LONG_PRESS_ACTION   3
    #define KEY_LONG_RELEASE_ACTION   4
    
    extern void user_timer_init(void);
    extern void add_system_time(void);
    extern void clear_time_cnt(U8 time_number);
    extern U8 check_time_arrive(U8 time_number, U16 time);

    二、按键事件

    1.1 user_key.c

    #include    "user_key.h"
    
    static U8 key_event_flag = 0;
    
    /* 需注意,当产生单击事件时,处理完毕后,记得释放按键事件,即调用,void rest_key_state();函数,释放按键。*/
    
    void user_key_init()
    {
      key_event_flag = KEY_NOT_ACTION ;
    }
    void user_key_scan(void)
    {
        U8 key_state = 1;                   // 按键未被触发时电平
        static U8 key_step = 0;
    
        key_state = GPIO_Read(GPIOA, 3);    // 按键端口赋值
    
        switch(key_step)
        {
            case 0:
                if(key_state)                                                    // 第0步,按键未被触发
                    clear_time_cnt(KEY_TRIGGER_TIMER);                           // 清除消抖时间
                else                                    
                    key_step++;                                                      // 按键触发 ,进入第1步
                break;
            case 1:
                if(key_state)                                                     // 再次确认按键是否按下 ,
                    key_step--;                                                   // 若没有,则返回第0步
                else                                                              // 如确认按键按下
                {
                    if(check_time_arrive(KEY_TRIGGER_TIMER, KEY_DEBOUNCE_TIME))  // 检查按键按下时间,是否超过设定消抖时间 ,若超过
                    {
                        clear_time_cnt(KEY_TRIGGER_TIMER);                        // 清除消抖时间
                        key_step++;                                                // 进入 第2步
                    } 
                }
                break;
            case 2:
                if(key_state)                                                    // 若超过设定消抖时间后,按键弹起
                {
                    clear_time_cnt(KEY_TRIGGER_TIMER);                            // 清除消抖时间
                    key_step++;                                                    // 进入第3部
                }
                else                                                            // 若超过设定消抖时间后,按键还未被释放
                {
                    if(check_time_arrive(KEY_TRIGGER_TIMER, KEY_LONG_PRESS_TIME)) //检查按键按下时间是否超过 长按设定时间 ,若超过
                    {
                        key_event_flag = KEY_LONG_PRESS_ACTION;                    // 发生长按 动作 按键按下
                        key_step += 2;                                            // 进入第4步
                    }
                }
                break;
            case 3:
                if(key_state)                                                    // 按键被释放
                {
                    if(check_time_arrive(KEY_TRIGGER_TIMER, KEY_DEBOUNCE_TIME)) // 检查释放时间是否满足 消抖时间 ,若满足
                    {
                        key_event_flag = KEY_CLICK_ACTION;                        // 则发生 单击 动作
                        key_step = 0;                                            // 返回 第 0 步
                    }
                }
                else                                                            // 若按键释放时间 未满足 消抖时间 ,则
                {
                    clear_time_cnt(KEY_TRIGGER_TIMER);                          // 清除消抖时间
                    key_step--;                                                    // 返回 第3步 ,继续判断按键按下时间,
                }
                break;
            case 4:
                if(key_state)                                                    // 长按 按键释放后
                {
                    if(check_time_arrive(KEY_TRIGGER_TIMER, KEY_DEBOUNCE_TIME)) //检查长按按键 释放 时间是否满足 按键消抖时间 
                    {
                        key_event_flag = KEY_LONG_RELEASE_ACTION;               // 则 发生 长按 动作释放按键
                        key_step = 0;                                           // 返回 第 0 步
                    }
                }
                break;
            default:
                break;
        }
    }
    uint8_t return_key_state() //返回按键 事件值  
    {
       return key_event_flag ;
    
    }
    
    
    void rest_key_state()   //按键释放
    {
      key_event_flag = KEY_NOT_ACTION ;
    }
    
    
    
     

    1.2 user_key.h

    ////============================================================
    //key
    //
    ////============================================================
    
    #define KEY_IO_INPUT    0
    #define KEY_IO_OUTPUT   1
    
    #define KEY_DEBOUNCE_TIME   8   //8MS
    #define KEY_LONG_PRESS_TIME 2300    //2s
    
    #define KEY_NOT_ACTION  0
    #define KEY_CLICK_ACTION   1
    #define KEY_LONG_PRESS_ACTION   3
    #define KEY_LONG_RELEASE_ACTION   4
    //============================================
    //user timer
    //============================================
    #define    USER_TIMER_AMOUNT    5
    
    #define    KEY_TRIGGER_TIMER    0
    #define VR_TIMEOUT_TIMER    1
    #define    RANDOM_TIMER        2
    #define KEY_CONTROL_TIMER     3
    #define USER_TIMER_0        4

    三、设置标志位

    1.1 user_flag.c

    #include "User_Flag.h"
    
    static idata uint8_t user_flag_array[USER_FLAG_AMOUNT_FLAG_NUMBER] = {0};
    
    
    void user_flag_init(void)
    {
        uint8_t i;
        for(i = 0; i < USER_FLAG_AMOUNT_FLAG_NUMBER; i++)
        {
            user_flag_array[i] = 0;
        }
        return;
    }
    
    //设置标志位
    void user_Set_flag( uint8_t flag_number , uint8_t flag_set_val )
    {
                user_flag_array[flag_number] = flag_set_val ;
    }
    
    
    //检测标志位是否是想要的数
    bit check_flag_arrive( uint8_t flag_number, uint8_t flag_dream_val  )
    {        
          if( user_flag_array[flag_number] == flag_dream_val )
                return 1;
            else
                return 0;
    }
    
    uint8_t get_arrive( uint8_t flag_number )   //返回标志位值
    {
    
      return user_flag_array[flag_number] ;
    
    
    }
    ////////////////////////////////////////////////////////////////////////////////////////////
    //void user_OTA_set_data( uint8_t flag_number , uint16_t flag_set_val )
    //{
    //  user_OTA_config[flag_number] = flag_set_val ;
    
    //}
    ////返回标志位数值
    //uint16_t return_dreanm_val( uint8_t  flag_number ) 
    //{
    
    // return user_OTA_config[flag_number];
    
    
    //}
    
    /////////////////////////////////////////////////////////////////////////////////////////

    1.2 user_flag.h

    #ifndef _User_Flag_H_
    #define _User_Flag_H_
    
    #include "includes.h"
    
    void user_flag_init(void);
    
    
    void user_Set_flag( uint8_t flag_number , uint8_t flag_set_val );
    
    bit check_flag_arrive( uint8_t flag_number,  uint8_t flag_dream_val );
    
    uint8_t get_arrive( uint8_t flag_number );
    
    
    //uint8_t return_dreanm_val( uint8_t  flag_number );
    
    
    //uint16_t return_dreanm_val( uint8_t  flag_number );
    
    //void user_OTA_set_data( uint8_t flag_number , uint16_t flag_set_val );
    
    
    
    
    
    #endif
  • 相关阅读:
    [BJOI2019] 光线
    C# 从零开始写 SharpDx 应用 笔刷
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    BAT 脚本判断当前系统是 x86 还是 x64 系统
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    win2d 通过 CanvasActiveLayer 画出透明度和裁剪
    PowerShell 拿到显卡信息
    PowerShell 拿到显卡信息
    win10 uwp 如何使用DataTemplate
    win10 uwp 如何使用DataTemplate
  • 原文地址:https://www.cnblogs.com/UPUPDay2152/p/10415090.html
Copyright © 2011-2022 走看看