赞
踩
基于蓝桥杯嵌入式开发板实现按键的单击,双击,长按检测与处理,使用定时器后台检测,防止占用前台资源,可以随便移植到任何单片机上。
#define KEY_B1 HAL_GPIO_ReadPin(KEY_B1_GPIO_Port, KEY_B1_Pin) #define KEY_B2 HAL_GPIO_ReadPin(KEY_B2_GPIO_Port, KEY_B2_Pin) #define KEY_B3 HAL_GPIO_ReadPin(KEY_B3_GPIO_Port, KEY_B3_Pin) #define KEY_B4 HAL_GPIO_ReadPin(KEY_B4_GPIO_Port, KEY_B4_Pin) /* 按键长按检测时间(单位:次数) 一次为定时器扫描一次的时间 */ #define KEY_LONG_PRESS_TIME 80 /* 按键双击间隔时间(单位:次数) 一次为定时器扫描一次的时间 */ #define KEY_DOUBLE_GAP_TIME 40 enum KEY_STATE { key_state_0 = 0, key_state_1 = 1, key_state_2 = 2, key_state_3 = 3 }; enum KEY_EVENT { key_no = 0, /* 无按键按下 */ key_click = 1, /* 单击 */ key_double = 2, /* 双击 */ key_long = 3 /* 长按 */ }; struct key{ bool key_input_val; enum KEY_STATE key_state_buff1; /* 按键执行状态1 */ enum KEY_STATE key_state_buff2; /* 按键执行状态2 */ enum KEY_EVENT key_real_result; /* 最终判断结果 */ unsigned char key_time_cnt1; /* 定时器1 */ unsigned char key_time_cnt2; /* 定时器2 */ };
static enum KEY_EVENT key_driver(int key_num) { enum KEY_EVENT key_result = key_no; switch (key[key_num].key_state_buff1) { case key_state_0: if (key[key_num].key_input_val == 0) { key[key_num].key_state_buff1 = key_state_1; /* 如果按键被按下,状态切换到按键消抖和确认状态 */ } break; case key_state_1: if (key[key_num].key_input_val == 0) { key[key_num].key_time_cnt1 = 0; key[key_num].key_state_buff1 = key_state_2; /* 按键仍处于按下状态 */ /* 消抖完成,计时器key_time_cnt1 开始计时 */ /* 状态切换到计时状态 */ } else key[key_num].key_state_buff1 = key_state_0; break; case key_state_2: if (key[key_num].key_input_val == 1) { key_result = key_click; /* 按键抬起,产生一次click操作 */ key[key_num].key_state_buff1 = key_state_0; } else if (++key[key_num].key_time_cnt1 >= KEY_LONG_PRESS_TIME) { /* 按键继续按下超过1000ms */ key_result = key_long; /* 返回长按操作 */ key[key_num].key_state_buff1 = key_state_3; /* 状态切换到按键释放状态 */ } break; case key_state_3: if (key[key_num].key_input_val == 1) /* 没按键按下了,回正常状态,防止按一次检测出两次单击 */ key[key_num].key_state_buff1 = key_state_0; break; } return key_result; } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM3) { enum KEY_EVENT key_result; key[0].key_input_val = KEY_B1;/* 读取按键值 */ key[1].key_input_val = KEY_B2; key[2].key_input_val = KEY_B3; key[3].key_input_val = KEY_B4; for (int i = 0; i < 4; i++) { key_result = key_driver(i); switch (key[i].key_state_buff2) { case key_state_0: if (key_result == key_click) { key[i].key_time_cnt2 = 0; key[i].key_state_buff2 = key_state_1; /* 第一次单击,不返回,到下一个状态判断是否有双击 */ } else key[i].key_real_result = key_result; /* 对于无键,长按,返回原事件 */ break; case key_state_1: if (key_result == key_click) /* 又一次单击,时间间隔小于500ms */ { key[i].key_real_result = key_double; /* 返回双击事件 */ key[i].key_state_buff2 = key_state_0; } else if (++key[i].key_time_cnt2 >= KEY_DOUBLE_GAP_TIME) { key[i].key_real_result = key_click; /* 500ms内没有再次出现单击事件,返回单击事件 */ key[i].key_state_buff2 = key_state_0; } break; } } } }
void key_proc() { if (key[0].key_real_result == key_click) { LCD_ClearLine(Line1); LCD_DisplayStringLine(Line1, (uint8_t *)" key0_click "); key[0].key_real_result = key_no;/* 清除按键事件,置为无键事件 */ } else if (key[0].key_real_result == key_double) { LCD_ClearLine(Line1); LCD_DisplayStringLine(Line1, (uint8_t *)" key0_double "); key[0].key_real_result = key_no; } else if (key[0].key_real_result == key_long) { LCD_ClearLine(Line1); LCD_DisplayStringLine(Line1, (uint8_t *)" key0_long "); key[0].key_real_result = key_no; } if (key[1].key_real_result == key_click) { LCD_ClearLine(Line2); LCD_DisplayStringLine(Line2, (uint8_t *)" key1_click "); key[1].key_real_result = key_no; } else if (key[1].key_real_result == key_double) { LCD_ClearLine(Line2); LCD_DisplayStringLine(Line2, (uint8_t *)" key1_double "); key[1].key_real_result = key_no; } else if (key[1].key_real_result == key_long) { LCD_ClearLine(Line2); LCD_DisplayStringLine(Line2, (uint8_t *)" key1_long "); key[1].key_real_result = key_no; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。