常见的单片机按键检测的方式多是在while(1)中以轮询的方式检测按键是否被按下,在进行延时消抖(10ms左右),防止误检测。这样做会长时间的占用单片机的CPU资源,不是一种高效的按键检测方式。我们可以采用外部中断加定时器的方式实现按键检测而又不会长时间占用CPU
STM32 常规的按键检测流程:
while(1)
{
if(KEY==0)
{
HAL_Delay(10); //延迟10ms再次检测,若还是低电平,代表按键被按下
if(KEY==0)
{
printf("key be pressed!!!\r\n");
}
}
}
STM32 HAL库外部中断+定时器检测按键的基本思路:外部中断设置下降沿触发,当按键按下单片机检测到下降沿后进入外部中断回调函数→在外部中断回调函数中打开定时器中断(定时时常设置为10ms)→在定时器中断回调函数中检测外部中断IO口电平,若依旧为低电平,代表按键被按下
具体操作步骤:
1.CubeMx配置
IO口PB1设置为外部中断上升沿触发模式,上拉
使用定时器1,时钟源选择内部时钟,预分频系数199、向上计数模式,计数值2399。
这里补充一下定时器计数时间的计算公式:Tout=(arr+1)*(psc+1)/Tclk,本例程中APB1外设时钟频率为48MHZ,故Tclk=1/48000000 所以Tout=(200*2400)/48us =10ms
2.单片机程序文章来源:https://uudwc.com/A/bE1nw
//当按键按下,单片机检测到下降沿后进入此外部中断回调函数
//在外部中断回调函数中开启定时器1
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==KEY_GPIO_PIN)
{
HAL_TIM_Base_Start_IT(&htim1);
}
}
//定时时间10ms到了进入此中断回调函数中
//在此回调函数中判断IO口电平状态,如果以就为低电平,代表按键被按下
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&htim1))
{
HAL_TIM_Base_Stop_IT(&htim1);
if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==0)
printf("key be pressed!!!\r\n");
}
}
总结一下,实现用外部中断检测按键,定时器延时消抖的关键步骤:文章来源地址https://uudwc.com/A/bE1nw
- 设置外部中断触发方式,计算预分频系数psc、计数值大小arr来确定时时间。
- 在外部中断回调函数中打开定时器,让其计数。
- 定时器溢出回调函数中,关闭定时器,再次检测按键IO口电平值。