实现流程
1:定义了7个按键对象,并且给这7个按键分配的了对应的7个触发事件(同一个按键的单
击和长按都属于不同按键对象)
2:按下按键->进入防抖->判断计数器返回的计数时间->根据时间来判断按键按下事件对应标志置1
3:process函数根据置 1 的事件,进入完成对应功能,把标志归 0 ,让按键的state = KEY_RESET或其他
.H
#ifndef __KEY_H
#define __KEY_H
#include "HAL_device.h"
#include "HAL_conf.h"
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#define PIN_STATE(n) GPIO_ReadInputDataBit(GPIOA, n)
enum key_state{ //定义按键状态
UP = 0,
DOWN = 1,
KEY_RESET = 2,
KEY_LONG_PRESS = 3,
KEY_LOCK = 4
};
typedef struct event{ //按键需要触发的情况
uint8_t set_click; //当按键触发之后,就将此标志置1,代表此按键或者组合按键被触发
uint8_t set_press_2s;
uint8_t set_redc_press_3s;
uint8_t set_redc_press_7s;
uint8_t set_redc_click;
uint8_t set_add_click;
uint8_t freeze_clicked;
uint8_t defrost_press_2s;
uint8_t add_redc_press_3s;
}s_key_event;
typedef struct key_menber{ //按键对象类型
uint16_t id;
uint8_t state;
}s_key_m;
typedef struct key{ //按键的对象
s_key_m key_1;
s_key_m key_2;
s_key_m key_3;
s_key_m key_4;
s_key_m key_23;
s_key_m key_24;
s_key_m key_34;
}s_key;
/******************************************/
void key_init(void);
void key_process(void);
#endif
#include "key.h"
#include "counter_delay.h"
#include "stdio.h"
#define ENTER_WAIT 60 //触发防抖延时
#define BACK_WAIT 60 //退出防抖延时
#if 1
#define KEY_NUM 7 //定义按键数量
s_key key; //按键结构体,存放所有按键
s_key_event key_event = {0}; //按键需要触发的事件
void key_state(void);
void key_init(void){
uint8_t i;
s_key_m * ptr = NULL;
ptr = (s_key_m *)&key;
for(i = 0;i < KEY_NUM ;i++){ ///给按键分配Id
(ptr+i)->id = (0xF1 + i);
(ptr+i)->state = UP;
}
}
void key_state(void){
//**************按键1
if( !PIN_STATE(GPIO_Pin_4)){
//防抖延时
if(key.key_1.state != KEY_RESET){
if( timer_state(key.key_1.id) == TIMING_END){
start_once_timer(DEFROST_PRESS_2S_ID , 8000, LOCK_TIMNG);
key.key_1.state = DOWN;
}
else{
start_timer(key.key_1.id,ENTER_WAIT,LOCK_TIMNG);
}
}
if(key.key_1.state == DOWN){
u32 count_value = timer_count_value(DEFROST_PRESS_2S_ID);
if((count_value >= 2000)&&(count_value <= 8000)&&(show_state == Normal_show_state)){
key_event.defrost_press_2s = 1; //触发事件
printf("按键2秒");
BUZZER_ON(KEY_S);
close_timer(DEFROST_PRESS_2S_ID, DESTROYED);
}
}
}
else{
if(key.key_1.state == DOWN){ //松开按键,判断事件类型
u32 counter = timer_count_value(DEFROST_PRESS_2S_ID);
if(counter <= 500){
key_event.freeze_clicked = 1; //触发事件
BUZZER_ON(KEY_S)
printf("制冷");
}
close_timer(DEFROST_PRESS_2S_ID,DESTROYED);
key.key_1.state = UP;
}
key.key_1.state = UP;
close_timer(key.key_1.id ,DESTROYED); //挂起定时器
}
//**************单点按键2
if((!PIN_STATE(GPIO_Pin_5))&&(PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_7))){
//设置防抖延时
if(key.key_2.state != KEY_RESET){
if( timer_state(key.key_2.id) == TIMING_END){ //进入事件计时
start_once_timer(SET_KEY_EVENT_ID, 8000, LOCK_TIMNG);
key.key_2.state = DOWN;
}
else{
start_timer(key.key_2.id,ENTER_WAIT,LOCK_TIMNG);
}
}
if(key.key_2.state == DOWN){
u32 count_value = timer_count_value(SET_KEY_EVENT_ID);
if((count_value >= 2000)&&(count_value <= 8000)&&(show_state == Normal_show_state)){
key_event.set_press_2s = 1; //触发事件
printf("仅设置键2S");
BUZZER_ON(KEY_S)
close_timer(SET_KEY_EVENT_ID, DESTROYED);
}
}
}
else{
if((key.key_2.state == DOWN)&&(PIN_STATE(GPIO_Pin_6))&&(timer_state(BACK_PROTECT_TIME_ID) == DESTROYED)){ //松开按键,判断事件类型
u32 count_value = timer_count_value(SET_KEY_EVENT_ID);
if(count_value <= 500U){
key_event.set_click = 1; //触发事件
BUZZER_ON(KEY_S);
printf("单击设置键");
}
close_timer(SET_KEY_EVENT_ID, DESTROYED);
}
key.key_2.state = UP;
close_timer(key.key_2.id ,DESTROYED); //挂起定时器
}
#if 1
/****************/
if( (!PIN_STATE(GPIO_Pin_5))&&(!PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_7))){
//设置 (-) 防抖延时
if(key.key_23.state != KEY_RESET){
if( timer_state(key.key_23.id) == TIMING_END){ //进入事件计时
start_once_timer(SET_REDC_PRESS_7S, 15000 , LOCK_TIMNG);
key.key_23.state = DOWN;
}
else{
start_timer(key.key_23.id,ENTER_WAIT,LOCK_TIMNG);
}
}
if(key.key_23.state == DOWN){
u32 counter = timer_count_value(SET_REDC_PRESS_7S);
if((counter >= 3000)&&(counter <= 7000)&&(show_state == Normal_show_state)){
key_event.set_redc_press_3s = 1; //触发事件
printf("SET- 3");
BUZZER_ON(KEY_S);
close_timer(SET_REDC_PRESS_7S,DESTROYED);
}
else if((counter >= 7000)&&(show_state == Menu_show_state)){
key_event.set_redc_press_7s = 1; //触发事件
printf("SET- 7");
BUZZER_ON(KEY_S);
close_timer(SET_REDC_PRESS_7S,DESTROYED);
}
}
}
else{
if(key.key_23.state == DOWN){ //松开按键,判断事件类型
u32 counter = timer_count_value(SET_REDC_PRESS_7S);
if(counter <= 500){
key_event.set_redc_click = 1; //触发事件
BUZZER_ON(KEY_S);
printf("SET-");
}
close_timer(SET_REDC_PRESS_7S,DESTROYED);
key.key_23.state = UP;
start_once_timer(BACK_PROTECT_TIME_ID, 200, LOCK_TIMNG);
}
key.key_23.state = UP;
close_timer(key.key_23.id ,DESTROYED); //挂起定时器
}
/****************/
if( (!PIN_STATE(GPIO_Pin_5))&&(PIN_STATE(GPIO_Pin_6)&&(!PIN_STATE(GPIO_Pin_7)))){
//设置 (+) 防抖延时
if( timer_state(key.key_24.id) == TIMING_END){ //进入事件计时
key.key_24.state = DOWN;
}
else{
start_timer(key.key_24.id,ENTER_WAIT,LOCK_TIMNG);
}
}
else{
if(key.key_24.state == DOWN){ //松开按键,判断事件类型
key_event.set_add_click = 1; //触发事件
printf("SET+");
BUZZER_ON(KEY_S);
start_once_timer(BACK_PROTECT_TIME_ID, 200, LOCK_TIMNG);
}
key.key_24.state = UP;
close_timer(key.key_24.id ,DESTROYED); //挂起定时器
}
#endif
//**************按键3
if( (!PIN_STATE(GPIO_Pin_6))&&(PIN_STATE(GPIO_Pin_5))){
//减少防抖延时
if((key.key_3.state != KEY_RESET)&&(key.key_3.state != KEY_LONG_PRESS)){
if( timer_state(key.key_3.id) == TIMING_END){
key.key_3.state = DOWN;
BUZZER_ON(KEY_S);
close_timer(key.key_3.id ,DESTROYED); //挂起定时器
}
else{
start_timer(key.key_3.id,ENTER_WAIT,LOCK_TIMNG);
}
}
else if(key.key_3.state == KEY_RESET){
if(timer_state(RDC_LONG_PRESS_ID) == TIMING_END){
if((show_state == Set_show_state)||(show_state == Set_temp_show_state)){ //只有设置数值才支持长按
key.key_3.state = KEY_LONG_PRESS;
}
close_timer(RDC_LONG_PRESS_ID,DESTROYED);
}
else{
start_timer(RDC_LONG_PRESS_ID, 700, LOCK_TIMNG);
}
}
else if(key.key_3.state == KEY_LONG_PRESS){
delay_ms(90);
}
}
else{
key.key_3.state = UP;
close_timer(RDC_LONG_PRESS_ID,DESTROYED);
close_timer(key.key_3.id ,DESTROYED); //挂起定时器
}
//**************按键4
if( (!PIN_STATE(GPIO_Pin_7))&&(PIN_STATE(GPIO_Pin_5))){
//增加防抖延时
if((key.key_4.state != KEY_RESET)&&(key.key_4.state != KEY_LONG_PRESS)){
if( timer_state(key.key_4.id) == TIMING_END){
key.key_4.state = DOWN;
BUZZER_ON(KEY_S);
close_timer(key.key_4.id ,DESTROYED); //销毁定时器
}
else{
start_timer(key.key_4.id,ENTER_WAIT,LOCK_TIMNG);
}
}
else if(key.key_4.state == KEY_RESET){
if(timer_state(ADD_LONG_PRESS_ID) == TIMING_END){
if((show_state == Set_show_state)||(show_state == Set_temp_show_state)){ //只有设置数值才支持长按
key.key_4.state = KEY_LONG_PRESS;
}
close_timer(ADD_LONG_PRESS_ID,DESTROYED);
}
else{
start_timer(ADD_LONG_PRESS_ID, 700, LOCK_TIMNG);
}
}
else if(key.key_4.state == KEY_LONG_PRESS){
delay_ms(90);
}
}
else{
key.key_4.state = UP;
close_timer(ADD_LONG_PRESS_ID,DESTROYED);
close_timer(key.key_4.id ,DESTROYED); //销毁定时器
}
/******锁屏按键组合********/
if((!PIN_STATE(GPIO_Pin_6))&&(!PIN_STATE(GPIO_Pin_7))&&(PIN_STATE(GPIO_Pin_5))){
if(timer_state(key.key_34.id) == TIMING_END){
start_once_timer(ADD_REDC_PRESS_ID,3400,LOCK_TIMNG);
key.key_34.state = DOWN;
}
else{
start_timer(key.key_34.id, ENTER_WAIT, LOCK_TIMNG);
}
if(key.key_34.state == DOWN){
u32 count = timer_count_value(ADD_REDC_PRESS_ID);
if(count >=3000){
key_event.add_redc_press_3s = 1; //触发事件
BUZZER_ON(KEY_S);
close_timer(ADD_REDC_PRESS_ID, DESTROYED);
}
}
}
else{
key.key_34.state = UP;
close_timer(key.key_34.id, DESTROYED);
close_timer(ADD_REDC_PRESS_ID, DESTROYED);
}
}
void key_process(void){
key_state(); //按键状态读取
//进入按键任务
#if 1
if((key.key_4.state == DOWN)||(key.key_4.state == KEY_LONG_PRESS)){ //支持数字长按连续切换的按键
//printf("+键 ");
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
if(key.key_4.state != KEY_LONG_PRESS){
key.key_4.state = KEY_RESET;
}
start_timer(key.key_4.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
}
if((key.key_3.state == DOWN)||(key.key_3.state == KEY_LONG_PRESS)){ //支持数字长按连续切换的按键
//printf("-键 ");
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
if(key.key_3.state != KEY_LONG_PRESS){
key.key_3.state = KEY_RESET;
}
start_timer(key.key_3.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
}
#endif
#if 1
//设置按键------------------------------------------------------------------------/
if(key_event.set_click){ //点击事件
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_2.state = KEY_RESET;//防止连续触发
key_event.set_click = 0;
close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
}
if(key_event.set_press_2s){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_2.state = KEY_RESET;//防止连续触发
key_event.set_press_2s = 0;
close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
}
if(key_event.set_redc_press_3s){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_23.state = KEY_RESET;
key_event.set_redc_press_3s = 0;
close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
}
if(key_event.set_redc_press_7s){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_23.state = KEY_RESET;
key_event.set_redc_press_7s = 0;
close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
}
if(key_event.set_redc_click){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_23.state = KEY_RESET;
key_event.set_redc_click = 0;
close_timer(BACK_NORMAL_ID, TIM_SUSPEND); //关掉无响应退出定时器
}
if(key_event.set_add_click){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key.key_24.state = KEY_RESET;
key_event.set_add_click = 0;
}
/*---------------------------------------------------------*/
#endif
if(key_event.freeze_clicked == 1){
//printf("制冷键 ");
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key_event.freeze_clicked = 0;
key.key_1.state = KEY_RESET;
start_timer(key.key_1.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
}
if(key_event.defrost_press_2s == 1){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key_event.defrost_press_2s = 0;
key.key_1.state = KEY_RESET;
start_timer(key.key_1.id,BACK_WAIT,LOCK_TIMNG); //退出防抖
}
if(key_event.add_redc_press_3s){
/**功能代码区-BEGAIN-**/
/**功能代码区-END-**/
key_event.add_redc_press_3s = 0;
key.key_34.state = KEY_RESET;
}
}
#endif
文章中的 start_timer()等接口是我的其它文章中的代码,可以参考我的文章,单片机软件定时器V2.0