问题

在使用按键配置外部中断时,使用HAL_Delay函数进行延时消抖,当进入中断时程序卡死无反应,去除HAL_Delay后恢复正常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

if(GPIO_Pin==KEY1_Pin)
{
HAL_Delay(20);/* 延时一小段时间,消除抖动 */
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==1)
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==1)
{
printf("KEY=1\n");

}

}
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
}
}

原因

查看HAL_Delay相关程序发现,HAL_Delay是通过滴答定时器的中断进行延迟。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @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)
{
}
}

进而查找滴答定时器相关初始化发现,在程序初始化时默认把滴答定时器的中断优先级设为最低

默认初始化

解决方法

我们可以在main的初始化后里加上如下指令把滴答定时器优先级调为最高,问题解决。

1
HAL_NVIC_SetPriority(SysTick_IRQn,0,0U);