问题描述
今天在学习STM32 HAL库外部中断,使用的是按键触发外部中断,想在外部中断里面写一个按键消抖,也就是在HAL库外部中断处理函数中使用了HAL_Delay() 函数,后来经过实验,在外部中断处理函数(void EXTI1_IRQHandler(void))和中断回调函数(void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin))里面都不能使用HAL_Delay(),使用就会卡死在延时这一步;
经过分析,也参考了别人的一些参考资料,发现网上的写的比较乱一点,自己总结了一下,以我理解的角度分析一下这些问题,(如有质疑之处,还请各位大佬批评指正);
首先详细描述一下这个问题,使用中断方式检测按键,程序运行后,按键产生的中断只能被触发一次,之后无法触发,而且一直卡在中断位置,无法退出中断;
原因分析:
认真看一下HAL_Delay函数,就可以分析出来问题:
/** * @brief This function provides minimum delay (in milliseconds) based * on variable incremented. * @note In the default implementation , SysTick timer is the source of time base. * It is used to generate interrupts at regular time intervals where uwTick * is incremented. * @note This function is declared as __weak to be overwritten in case of other * implementations in user file. * @param Delay specifies the delay time length, in milliseconds. * @retval None */
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while((HAL_GetTick() - tickstart) < wait)
{
}
}
这是延时函数的原型,有着 __weak 的标识,意味着你可以自己写一个延时函数并用同样的函数名。同时可以看到函数上方有说明,第二条注意事项清楚地说道:计时器的时基来源是 SysTick定时器,且在固定时间间隔内产生中断。Interrupt这一词是问题的关键,既然是中断,势必就有优先级,如果在中断里面HAL_Delay会卡死,而main函数则不会,那可能是优先级问题造成的。
系统滴答定时器(System tick timer)的优先级默认就是最低;
外部中断处理的优先级比系统滴答定时器优先级高;
在整个按键触发的过程中,按键按下触发了外部中断,转去执行外部中断函数,但是在外部中断里面调用了HAL_Delay()这个延时程序来消除按键抖动。HAL_Delay()使用了系统滴答定时器来精确定时。外部中断处理的优先级比系统滴答定时器优先级高。所以系统滴答定时器又被按键中断打断,HAL_Delay()遭到了阻塞。所以,程序卡死在HAL_Delay()这里,整个程序处于卡死状态。
按键触发中断处理程序 --> HAL_Delay() --> 系统滴答定时器(未执行)–>外部中断处理 --> HAL_Delay() (卡死)
如果HAL_Delay()需要被外部中断处理程序调用,系统滴答定时器必须比外部中断要高,否则调用者的中断处理程序将被阻塞。
解决方案:
一种解决办法是:
采用while(t–);代替延时函数;
经过查资料:
t=3127;
while(t--);
大致相当于HAL_Delay(1);即延时一毫秒;参考别人计算的t值,可能并不准确
可以自习写一个函数:
void ms_Delay(uint16_t t_ms)
{
uint32_t t=t_ms*3127;
while(t--);
}
也可以在函数里面直接写:
uint16_t t=3127*ms;
while(t--);
还有另一种解决办法是更改系统滴答定时器和外部中断的优先级,将系统滴答定时器的优先级设置的比外部中断要高文章来源:https://www.toymoban.com/news/detail-840427.html
将外部中断的优先级设置的比系统滴答定时器优先级要高文章来源地址https://www.toymoban.com/news/detail-840427.html
到了这里,关于STM32 HAL库 中断处理中使用延时函数(HAL_Delay)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!