在按键的使用过程中,有许多的按键扩展方式,比如区别按键的长按短按以及双击,这里将实现这些功能
硬件连接、cubemx配置、LED封装函数,请看我的上一篇文章,这里只介绍按键的封装函数
实现按键长短按
中断回调函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
volatile uint8_t j = 0;
volatile uint8_t key_short = 0; // 短按标志
volatile uint8_t key_long = 0; // 长按标志
uint16_t key_t = 0; // 计时器(单位:10ms,TIM3中断周期为10ms)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
uint8_t k = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
switch (j) {
case 0: // 初始状态,等待按键按下
if (k == 0) { // 检测到按下
j = 1; // 进入消抖确认状态
key_t = 0;
}
break;
case 1: // 消抖确认按下(10ms)
if (k == 0) { // 确认稳定按下
j = 2;
key_t = 0;
}
else { // 抖动,回到初始
j = 0;
}
break;
case 2: // 检测按持续时间
if (k == 1) { // 按键松开
if (key_t <= 100) { // 短按(≤1秒)
key_short = 1;
} else { // 长按(>1秒)
key_long = 1;
}
j = 0; // 复位状态机
} else { // 持续按下
key_t++;
}
break;
}
}
}
主函数main.c
HAL_TIM_Base_Start_IT(&htim3);
开启定时器
while (1)
{
if(key_long==1)//按键长按LED灯熄灭
{
led_p(0);
key_long=0;//将标志位清零
}
if(key_short==1)//按键短按LED灯点亮
{
led_p(1);
key_short=0;//将标志位清零
}
}
这样就实现了长按和短按了
实现按键双击
中断回调函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
//按键单击双击(1S内没有按下第二次默认为单击)
volatile uint8_t j = 0;
volatile uint8_t key_d = 0; // 单击标志
volatile uint8_t key_s = 0; // 双击标志
uint16_t key_t=0; // 计时器(单位:10ms)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3) //TIM3中断周期为10ms
{
uint8_t k = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);
switch(j)
{
case 0: // 初始状态,等待按键按下
if(k == 0) { // 检测到按下
j = 1; // 进入消抖确认状态
key_t = 0;
}
break;
case 1: // 消抖确认按下
if(k == 0) { // 仍然按下
j = 2; // 进入等待松开状态
key_t = 0;
} else { // 抖动,回到初始
j = 0;
}
break;
case 2: // 等待第一次松开
if(k == 1) { // 已松开
j = 3; // 进入等待双击状态
key_t = 0; // 重置双击计时
}
break;
case 3: // 等待第二次按下(双击检测窗口)
if(k == 0) { // 第二次按下
j = 4; // 进入第二次消抖
key_t = 0;
}
else {
key_t++;
if(key_t >= 100) { // 1秒超时
key_d = 1; // 触发单击
j = 0; // 复位状态机
}
}
break;
case 4: // 确认第二次按下
if(k == 0) { // 仍然按下
j = 5; // 进入等待第二次松开
key_t = 0;
} else { // 抖动,回到双击检测
j = 3;
}
break;
case 5: // 等待第二次松开
if(k == 1) { // 松开完成双击
key_s = 1; // 触发双击标志
j = 0; // 复位状态机
}
break;
}
}
}
主函数main.c
HAL_TIM_Base_Start_IT(&htim3);
开启定时器
while (1)
{
if(key_d==1)//按键单击LED灯点亮
{
led_p(1);
key_d=0;//将标志位清零
}
if(key_s==1)//按键双击LED灯熄灭
{
led_p(0);
key_s=0;//将标志位清零
}
}
这样就实现了单击和双击了