实用按键事件检测(单击、长按)

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

一、定时功能函数

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

 

posted @ 2019-02-21 20:36  一切都会好  阅读(3758)  评论(0编辑  收藏  举报