STM32G071KBU EXTI中断触发HardFault_Handler错误问题求助
故障原因排查
- 核心诱因是按键机械抖动未做处理:普通机械按键按下/松开时会产生数ms~数十ms的电平抖动,对应产生多个连续的上升/下降沿,你的EXTI配置为下降沿触发且中断优先级为最高级0,抖动会导致短时间内连续触发上百次中断。
- 最终触发HardFault的根因是栈溢出:最高优先级中断连续触发时,主程序无法运行,中断请求会不断嵌套压栈,栈空间耗尽后程序跑飞进入HardFault_Handler,这也是你用LL库、HAL库都能复现问题的核心原因,和库实现无关。
- 次要潜在问题:当前用自增操作修改
m_led_status仅为切换LED状态无必要,虽不会直接触发故障,但存在无意义的变量溢出风险。
解决方案
1. 新增按键消抖逻辑(必改)
二选一即可,优先推荐硬件消抖实现最简单:
- 硬件消抖:在按键的信号引脚和GND之间并联100nF~1μF的陶瓷电容,直接滤除抖动产生的窄脉冲尖峰,无需修改软件。
- 软件消抖:在EXTI中断触发后先关闭PB2对应的EXTI中断,同时启动一个10ms的硬件定时器,定时器溢出中断中再清除EXTI挂起标志、重新打开EXTI中断,避免抖动重复触发。
示例软件消抖修改参考:
// 新增全局变量记录中断有效标记 volatile static uint8_t g_exti_valid = 1; void EXTI2_3_IRQHandler(void) { if (LL_EXTI_IsActiveFallingFlag_0_31(LL_EXTI_LINE_2) != RESET) { LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_2); // 消抖期直接忽略无效触发 if (g_exti_valid) { g_exti_valid = 0; m_led_status ^= 1; // 替换自增为直接翻转,更安全 // 这里启动你配置的10ms定时器即可 LL_TIM_EnableCounter(TIM2); LL_TIM_EnableIT_UPDATE(TIM2); } } } // 定时器更新中断服务函数 void TIM2_IRQHandler(void) { if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) { LL_TIM_ClearFlag_UPDATE(TIM2); LL_TIM_DisableCounter(TIM2); g_exti_valid = 1; } }
2. 辅助优化项
- 检查启动文件中
Stack_Size配置,建议至少设置为0x400(1KB),避免栈空间过小导致偶发溢出。 - 无需将EXTI中断优先级设为最高级0,可调整为2或更低,避免阻塞内核异常处理逻辑。
- 替换
m_led_status++为m_led_status ^= 1,直接实现状态翻转,消除无意义的变量溢出。
内容的提问来源于stack exchange,提问作者Marco Arigliani
相关产品推荐
相关产品推荐

