一、簡介
????????窗口看門狗用于監測單片機程序運行時效是否精準,主要檢測軟件異常,一般用于需要精準檢測程序運行時間的場合。????????
????????窗口看門狗的本質是一個能產生系統復位信號和提前喚醒中斷的6位計數器(有的地方說7位。其實都無所謂,本質是一樣的)。
??????? 產生復位條件:
- 當遞減計數器值從 0x40 減到 0x3F 時復位(即T6位跳變到0)
- 計數器的值大于 W[6:0] 值時喂狗會復位。
????????產生中斷條件:
- 當遞減計數器等于 0x40 時可產生提前喚醒中斷 (EWI)。
在窗口期內重裝載計數器的值,防止復位,也就是所謂的喂狗。
二、WWDG工作原理及框圖
?三、WWDG寄存器及函數介紹
????????窗口看門狗內有一個7位的遞減計數器,并可以設置成自由運行。它可以被當成看門狗用于在發生問題時復位整個系統。它由主時鐘驅動,具有早期預警中斷功能;在調試模式下,計數器可以被凍結。
3.1 控制寄存器
3.2 配置寄存器
3.3 狀態寄存器
3.4 寄存器映像
3.5 函數
?等......
配置步驟
四、WWDG溢出時間計算
在上面的超時公式中:周期(時間 = Tpclk1) = 頻率的倒數 =?PCLK1(頻率)
4096 * 2^WDGTB / PCLK1? = 數一個數的時間單位是ms
PCLK1 = 36MHZ( 常等于)
(T[5:0]+1) = 個數
五、看門狗實驗
5.1 實驗目的
????????開啟窗口看門狗,計數器值設置為 0X7F ,窗口值設置為 0X5F ,預分頻系數為 8 。在 while 循環里喂狗,同時翻轉 LED1 狀態;在提前喚醒中斷服務函數進行喂狗,同時翻轉 LED2 狀態。
這里設置的窗口上限值為:
從開始計數,到記完數要復位的地方,也就是0X7F - 0X3F這段記58.25ms
復制項目文件夾19-串口打印功能,重命名位28-WWDG窗口看門狗
新建文件夾wwdg
打開項目
加載文件
加入wwdg驅動文件
代碼:
main.c
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "wwdg.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init();//初始化led燈uart1_init(115200);wwdg_init(0x7f,0x5f,WWDG_PRESCALER_8);printf("hello word!\r\n");if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET){printf("窗口看門狗復位!\r\n");__HAL_RCC_CLEAR_RESET_FLAGS();}elseprintf("外部復位!\r\n");while(1){
// delay_ms(50);
// wwdg_feed();
// led1_Toggle();}
}
wwdg.c
#include "wwdg.h"
#include "led.h"WWDG_HandleTypeDef wwdg_handle = {0};//初始化窗口看門狗函數
void wwdg_init(uint8_t tr,uint8_t wr,uint32_t psc)
{wwdg_handle.Instance = WWDG;wwdg_handle.Init.Counter = tr;//計數器的值wwdg_handle.Init.Prescaler = psc;//預分頻系數wwdg_handle.Init.Window = wr;//窗口上限值wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;//窗口看門狗早期喚醒啟用HAL_WWDG_Init(&wwdg_handle);
}//msp函數初始化
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{__HAL_RCC_WWDG_CLK_ENABLE();HAL_NVIC_SetPriority(WWDG_IRQn,2,2);//搶占優先級和響應優先級HAL_NVIC_EnableIRQ(WWDG_IRQn);
}//中斷服務函數
void WWDG_IRQHandler(void)
{HAL_WWDG_IRQHandler(&wwdg_handle);
}//提前喚醒回調函數
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{//wwdg_feed();led2_Toggle();
}//喂狗函數
void wwdg_feed(void)
{HAL_WWDG_Refresh(&wwdg_handle);
}
wwdg.h
#ifndef __WWDG_H__
#define __WWDG_H__#include "sys.h"void wwdg_init(uint8_t tr,uint8_t wr,uint32_t psc);
void wwdg_feed(void);#endif
5.2 出現的結果
5.2.1 檢驗出現的結果1
當主函數為下面這段代碼時,出現的結果是:
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "wwdg.h"int main(void)
{HAL_Init(); /* 初始化HAL庫 */stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */led_init();//初始化led燈uart1_init(115200);wwdg_init(0x7f,0x5f,WWDG_PRESCALER_8);printf("hello word!\r\n");while(1){ }
}
此時wwdg.c文件中,有喂狗操作。
串口窗口顯示結果為
并且開發板LED2瘋狂閃爍,表示在喚醒回調函數中成功喂狗
5.2.2 檢驗出現的結果2
當主函數為下面代碼時:
此時wwdg.c文件中,有喂狗操作。
串口窗口顯示結果為
并且開發板LED2瘋狂閃爍,表示由外部復位,并且在此時成功喂狗
5.2.3 檢驗出現的結果3
主函數代碼不變,wwdg.c文件如下圖所示:
串口窗口顯示結果為
并且開發板LED2瘋狂閃爍,表示此時沒有喂狗,看數數溢出由,窗口看門狗是否復位
5.2.4 檢驗出現的結果4
主函數代碼如下圖所示:
wwdg.c文件代碼如下:
串口窗口顯示結果為
LED1瘋狂閃爍,這個時候延遲10ms喂狗的,此時喂狗在窗口期前,這個時候數數溢出由看門狗會復位
5.2.5 檢驗出現的結果5
主函數代碼如下:
串口窗口顯示如下:
LED1瘋狂閃爍,在while函數中喂狗成功
5.3 關于疑問
在wwdg.c文件中,psc預分頻器的定義,這里使用的是uint16_t,沒有報錯
我的理解是:4096 * 8 = 32768 = 1000 0000 0000 0000,十六位夠用
這里如果定義的是uint8,則會報錯,如下圖所示:
翻譯如下: