蓝桥杯嵌入式按键长短按移植
蓝桥杯嵌入式按键长短按移植
文章目录
- 蓝桥杯嵌入式按键长短按移植
- 1、外设占用,基本定时器1个,配置为10ms中断
- 2、按键代码
1、外设占用,基本定时器1个,配置为10ms中断
初始化后,打开中断。
HAL_TIM_Base_Start_IT(&htim4);//打开定时器中断
2、按键代码
key.c
:
#include "key.h"
#include "oled.h"struct keys g_key[4] = {0,0,0,0};/*** @brief 按键扫描函数,需要10ms执行一次*
*/
void key_scan(void)
{//读取本次扫描电平状态g_key[0].state_pin = HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin);g_key[1].state_pin = HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin);g_key[2].state_pin = HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin);g_key[3].state_pin = HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin);//轮询按键消抖for(int i=0;i<4;i++){switch(g_key[i].state_step){case 0://首次按下{if(g_key[i].state_pin == 0){g_key[i].state_step = 1; //跳转到消抖状态g_key[i].time_press = 0; //清零计时}}break;case 1://10ms后按键仍按下,说明电平已稳定,完成消抖{if(g_key[i].state_pin == 0){// g_key[i].flag_press = 1; //记录短按生效g_key[i].state_step = 2; //跳转到松手检测}elseg_key[i].state_step = 0; //否则视为抖动,重新检测}break;case 2://读取到松手,本次扫描结束{if(g_key[i].state_pin == 1)//松手{if(g_key[i].time_press < 100)//小于1s视为短按{g_key[i].flag_press = 1;//短按松手生效}else if(g_key[i].time_press >= 100)//大于1s视为长按{g_key[i].flag_press_long = 1;//长按松手生效}g_key[i].state_step = 0; //回到最初状态}else{g_key[i].time_press++;//未松手就计时
// if(g_key[i].time_press >= 100)
// g_key[i].flag_press_long = 1;//长按未松手生效,放在这里会由bug,按完不松手会与key_proc里的清零一直冲突,相当于长按一直生效}}break;}}
}/*** @brief 按键动作处理函数,响应按键动作* */
void key_proc(void)
{static uint8_t a = 0;static uint8_t b = 0;if(g_key[0].flag_press == 1)//按键1动作处理{OLED_ShowNum(0,0,a++,3,16,1);OLED_Refresh();g_key[0].flag_press = 0;//记住用完后一定要清零,才能继续使用}if(g_key[0].flag_press_long == 1)//按键1动作处理{HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);g_key[0].flag_press_long = 0;//记住用完后一定要清零,才能继续使用}if(g_key[1].flag_press == 1)//按键2动作处理{OLED_ShowNum(0,16,b++,3,16,1);OLED_Refresh();g_key[1].flag_press = 0;//记住用完后一定要清零,才能继续使用}if(g_key[1].flag_press_long == 1)//按键2动作处理{HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);g_key[1].flag_press_long = 0;//记住用完后一定要清零,才能继续使用}
}
key.h
:
#ifndef __KEY_H
#define __KEY_H#include "main.h"struct keys
{uint8_t state_step; //判断进程uint8_t state_pin; //按键电平状态uint8_t flag_press; //按键按下标志位uint16_t time_press; //记录按下时间*10msuint8_t flag_press_long; //长按标志位
};extern struct keys g_key[];void key_scan(void);
void key_proc(void);
#endif
定时器中断
:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM4)//10ms按键扫描{key_scan();}
}
main.c
:
while (1){key_proc();}