在項目中有時候會遇到單片機莫名奇妙復位的情況,爲了判斷是那種原因引起復位,就需要對單片機的復位源進行判斷。現用STM32F103C8T6單片機進行測試。
先看看單片機復位源都有哪些?
在STM32中文參考手冊中可以看到,復位源可以通過狀態寄存器來讀出。
於是寫一段程序來讀取復位狀態寄存器:
void Check_Rst(void)
{
printf(" CSR = %x\r\n", RCC->CSR);
if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET ) // NRST 引腳復位
{
printf("PIN reset \r\n");
}
if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET ) // 上電掉電覆位
{
printf("POR/PDR reset \r\n");
}
if(RCC_GetFlagStatus(RCC_FLAG_SFTRST) != RESET ) // 軟件復位
{
printf("Software reset \r\n");
}
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET ) // 獨立看門狗復位
{
printf("Independent watchdog reset \r\n");
}
if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET ) // 窗口看門狗復位
{
printf("Window watchdog reset \r\n");
}
if(RCC_GetFlagStatus(RCC_FLAG_LPWRRST) != RESET ) // 低功耗復位
{
printf("(Low-power reset \r\n");
}
RCC_ClearFlag(); //清除復位標誌
printf("\r\n");
}
通過串口將信息打印出來。
現在寫個程序測試,引腳復位、掉電覆位、看門狗復位都比較好測試。就是軟件復位要用代碼實現。通過查找資料發現軟件復位可以分爲系統復位和內核復位。系統復位會復位所有硬件電路,包括IO口狀態。內核復位只復位內核,不影響硬件電路。
系統復位實現代碼如下:
//系統復位 所有電路都會復位
void mcuSysRestart(void)
{
__set_FAULTMASK(1); //關閉所有中斷
NVIC_SystemReset(); //系統復位 源碼見 core_cm3.h 文件 static __INLINE void NVIC_SystemReset(void) 函數
}
內核復位代碼如下:
//內核復位 不會影響外設和其他電路
void mcuCoreRestart(void)
{
__DSB();
//置位VECTREST
SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
SCB_AIRCR_VECTRESET_Msk);
__DSB();
while(1);
}
在程序中通過不同的按鍵控制不同復位情況,打印信息如下:
上電覆位:
按復位鍵復位:
獨立看門狗復位:
窗口看門狗復位:
系統復位:
內核復位:
通過上面復位測試可以發現,每種復位都會檢測到NRST 引腳復位,難道每種復位都會將復位引腳電平拉低嗎?通過示波器看看復位引腳電平:
通過復位引腳波形可以看出,在其它復位情況發生時,復位引腳會有一個很短的負脈衝。說明其他復位源產生時,復位引腳電平也會變化。看來上面程序檢測是正確的。