按键外部中断消抖
实验介绍
写这篇文章来源于最近面试问的一个问题采用外部中断,如何消抖,当时回答的是延时,但其实这样外部中断就没有采用的意义了,然后之后备赛蓝桥杯,也遇到这个问题,在蓝桥杯中如果不考虑时间的话,采用延时是可以很好解决了,但这里我想用另外一种想法来解决,也不知道这样有没有用emmm…
中断
中断就是指CPU正在处理某件事件时,外部发生了另一事件(例如一个电平的变化、一个脉冲沿的发生、定时计数器溢出等)请求CPU迅速去处理,于是,CPU暂停当前的程序,转去处理所发生的事情;当处理完所发生的事情后,再回到原来被暂停的程序处继续原来的工作。
中断的作用:
(1)提高CPU工作效率。
(2)具有实时处理功能。在实时控制系统中,现场各种参数和状态的变化是随机发生的,要求CPU能快速响应、及时处理。有了中断系统,这些参数和状态的变化可以作为中断信号,根据要求随时向CPU发出中断申请,请求CPU及时处理,如中断条件满足,CPU马上就会响应进行相应的处理,从而实现实时处理。
(3)具有故障处理功能。单片机应用系统在实际运行中,常会出现一些故障。例如电源突然掉电、硬件自检出错、运算溢出等。利用中断,可通过中断系统由故障源向CPU发出中断请求,再由CPU转到相应的故障处理程序进行处理。
(4)实现分时操作。单片机应用系统通常需要控制多个外围设备同时工作。
按键消抖
一般按键消抖有两种方法:
①延时,抖动时间是5-10ms,所以只需要延时10ms再检测是否被按下即可
②多次检测,抖动时间是5-10ms,按键按下持续的时间有100ms,我们可以取80ms,每10ms判断一次是否被按下了,当连续8次(也就是80ms)按键都是按下则可以确定按键已经稳定按下
按键松开也是当如果连续8次(也就是80ms)按键都是松开则可以确定按键已经稳定松开
基于外部中断的按键消抖
其实消抖目的就是为了不让按键按下的程序执行多次,那么我们进行松手检测时可以采用设置标志位来实现,当进入中断时先判断标志位是否为0,为0则进行中断处理,然后执行完对应的程序后将中断置为0,再进行下一次中断判断。
中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(key_flag==0)
{
if(GPIO_Pin==GPIO_PIN_0)
{
key_flag=1;
}
else if(GPIO_Pin==GPIO_PIN_1)
{
key_flag=2;
}
else if(GPIO_Pin==GPIO_PIN_2)
{
key_flag=3;
}
}
}
执行程序函数
void key_mask()
{
switch(key_flag)
{
case 1:
value_1++;
sprintf((char*)str,"value=%d",value_1);
LCD_DisplayStringLine(Line2,(unsigned char *)str);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
key_flag=0;
break;
case 2:
value_2++;
sprintf((char*)str,"value=%d",value_2);
LCD_DisplayStringLine(Line3,(unsigned char *)str);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
key_flag=0;
break;
case 3:
value_3++;
sprintf((char*)str,"value=%d",value_3);
LCD_DisplayStringLine(Line4,(unsigned char *)str);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
key_flag=0;
break;
}
}
在主函数进行调用
while (1)
{
key_mask();
}
emmm最后发现这种方法呢,比不加消抖好,但仍然存在问题,水平有限,希望大佬们能提出不同的意见