長時間運行任務(如電機運動、數據采集)需支持用戶中途取消並重置系統。方案:配置外部中斷(如按鍵),在 ISR 中觸發軟件復位,系統重新從 main() 執行。
void EXTI_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_LineX) != RESET) {
EXTI_ClearITPendingBit(EXTI_LineX);
__set_FAULTMASK(1); // 關閉所有中斷,防止復位過程被打斷
NVIC_SystemReset(); // 請求系統復位
}
}
__set_FAULTMASK(1):設置 Fault Mask 寄存器,屏蔽所有可屏蔽中斷與 Fault 異常,保證復位序列原子性。NVIC_SystemReset():向 SCB->AIRCR 寫入 VECTKEY | SYSRESETREQ,觸發內核級系統復位(等效於按下復位鍵)。NVIC_SystemReset() 的 while(1) 死循環static __INLINE void NVIC_SystemReset(void) {
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
SCB_AIRCR_SYSRESETREQ_Msk);
__DSB();
while(1); // 等待復位發生
}
現象:程序停在 while(1),復位未發生。
原因:硬件復位電路(如 SP809 復位芯片)干擾內核復位請求,導致 NRST 引腳無法被內核拉低。
解決**:移除板載復位芯片(SP809),改用 MCU 內部復位電路或簡單 RC 復位電路。
注意**:同事另一項目同款復位芯片卻正常工作,具體差異待進一步分析(可能涉及電源序列、電容充放電時間等)。
現象**:按鍵按下一次,EXTI_IRQHandler 執行兩次。
解決**:在 ISR 入口立即關閉該外部中斷通道(EXTI->IMR &= ~EXTI_LineX),ISR 末尾重新開啟(EXTI->IMR |= EXTI_LineX)。
根因分析**:ST 官方 FAQ 指出,若中斷標誌位清除過晚,外設可能再次觸發。嘗試將 EXTI_ClearITPendingBit 前移仍無效,最終採用「進 ISR 即屏蔽中斷」策略繞過。具體硬件時序原因待深究。
NVIC_SystemReset() 前**務必**關閉全局中斷(__set_FAULTMASK(1) 或 __disable_irq())。STM32 軟件復位雖有標準庫函數,但硬件復位電路干擾、中斷重入等實際工程問題需具體分析。「ISR 屏蔽中斷 + 關全局中斷 + 復位請求」是相對穩健的組合拳;若條件允許,優先考慮主循環協作式復位,避免在中斷上下文執行復位操作。