实用按键事件检测(单击、长按)
前断时间阅读“大佬”程序,发掘出有几个好用的,自定义的函数,此类函数巧妙使用返回值,传递参数,设置标志位、定时、赋值等功能,今晚特此来分享下。
一、定时功能函数
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