目录
[HAL库:中断 方式按键检测:抬起执行、按下执行、长按短按检测、延时执行](#HAL库:中断 方式按键检测:抬起执行、按下执行、长按短按检测、延时执行)
HAL库:中断 方式按键检测:抬起执行、按下执行、长按短按检测、延时执行
注意事项:
-
中断线列表 在stm32xb.h中 有写
-
中断函数 在.s汇编启动文件中 有写
-
HAL库在各个外设已经做好了检测外部中断等等的函数。对回调函数这些不太理解的 具体见这篇博客HAL库中断处理函数 及 weak弱声明中断回调函数-CSDN博客
-
HAL_Delay阻塞问题
在这里,消抖的方法时使用较为简单的HAL_Delay的延时函数。
在ST官方中,对HAL_Delay是这样描述的:
大概的意思是:HAL_Delay函数是基于系统滴答定时器中断来累增计数产生延时效果。是这表明如果该函数被调用别的中断处理函数里,系统滴答定时器的中断就必须比这个外设中断的优先级高,否则这个外设中断将被阻塞。 (可以理解为,滴答定时器被一个优先级更高的中断给阻塞了。而这个中断又需要大大定时器。)
这里只学习使用,一般不用这种方式
初始化部分:
-
输入值为模式。0为按下执行,1抬起执行
-
根据选择的模式,设置检测上升沿、下降沿进入中断(按键低电平有效)
- 按下执行:检测下降沿
- 抬起执行:检测上升沿
-
HAL_Delay阻塞问题:设置滴答定时器为最高优先级
-
配置优先级和使能中断线
void KEY_Init_IT(uint8_t mode)
{
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟GPIO_InitTypeDef GPIO_InitStructure; if(mode == 0) //判断模式:是否为按下执行 { GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING; //下降沿进入中断 模式 } else //否则为抬起执行 { GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING; //上升沿进入中断 模式 } GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_10; GPIO_InitStructure.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);//配置PB 10 、 0的模式 //HAL库默认中断分组为组4 抢占4 响应0 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); //设置中断优先级 HAL_NVIC_SetPriority(EXTI0_IRQn,4,0); //抢占和响应 HAL_NVIC_EnableIRQ(EXTI0_IRQn); //使能 HAL_NVIC_SetPriority(EXTI15_10_IRQn,4,0); //抢占和响应(这里设置的抢占优先级更高) HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //使能 HAL_NVIC_SetPriority(SysTick_IRQn,0,0);//设置滴答定时器为最高优先级,否则会卡死在HAL_Delay函数中
}
回调函数部分
对抬起和按下分别判断。 在按下有效时只可能进入按下判断部分; 在抬起有效时,只可能进入抬起检测部分。 因为波动导致时间不够会直接退出中断。
//定义 (强声明的) HAL库回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)//根据进入时的Pin值来选择不同的动作
{
case GPIO_PIN_0 :
{
if(KEY1_IN == 0)//判断按下
{
HAL_Delay(10); //消抖
if(KEY1_IN == 0) //确实按下
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15);
}
}
else if(KEY1_IN == 1)//判断抬起
{
HAL_Delay(10); //消抖
if(KEY1_IN == 1) //确实抬起
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15);
}
}
break;
}
case GPIO_PIN_10 :
{
if(KEY2_IN == 0)//判断按下
{
HAL_Delay(10); //消抖
if(KEY2_IN == 0) //确实按下
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15);
}
}
else if(KEY2_IN == 1)//判断抬起
{
HAL_Delay(10); //消抖
if(KEY2_IN == 1) //确实抬起
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_15);
}
}
break;
}
}
}