1.WWDG介紹
1.1 WWDG簡介
? 上一章我們已經介紹了IWDG,知道它的工作原理就是一個12位遞減計數器不斷遞減計數,當減到0之前還未進行喂狗的話,產生一個MCU復位。
窗口看門狗WWDG其實和獨立看門狗類似,它是一個7位遞減計數器不斷的往下遞減計數,當減到一個固定值 0X40 時還不喂狗的話,產生一個MCU復位,這個值叫窗口的下限,是固定的值,不能改變,這個和獨立看門狗是類似的。只不過獨立看門狗是減0之前要復位,這里要在0X40之前要復位。
不同的是,窗口看門狗的計數器的值在減到某一個數之前喂狗的話也會產生復位,這個值叫窗口的上限,上限值由用戶獨立設置。窗口看門狗計數器的值必須在上窗口和下窗口之間可以刷新(喂狗),才不會產生復位。這也是窗口看門狗中“窗口”兩個字的含義。????? ?
這很容易理解,7位計數器的最大值是127,? ?窗口下限 0X40是64,這是固定的。假定我將窗口上限值設為100,那么,當窗口看門狗啟動后,它就從127開始遞減,在它減到100之前,不能去刷新也就是重新裝載100,否則會產生復位。只有在其遞減到100以下,64之前,才可以重載100。如果掉到64以下(64來還不會復位,63就復位)還沒有重載(喂狗)100,那么也會產生復位。
1.2 WWDG結構框圖
? 要更好的理解窗口看門狗,就需要了解它內部的結構。
(1)標號1:WWDG時鐘(在APB1總線上,因此需要將APB1總線時鐘打開.APB1總線時鐘通常為36MHZ。)
(2)標號2:WDG預分頻器器
? 分頻后的計數器時鐘為:CK_CNT= PCLK1/4096/(2^WDGTB)。
除以4096是中文參考手冊內公式規定,沒有為什么。WDGTB叫做分頻因子,取值可以是0,1,2,3四種情況。
假定取值為0,那么2的0次方為1.CK_CNT= PCLK1/4096/1=36MHZ/4086=8.78KHZ。
(3)標號3:7位遞減計數器
? 窗口看門狗的超時時間計算公式如下:
? Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /PCLK1;
? ????????Twwdg為窗口看門狗的超時時間,單位為ms。
? ????????PCLK1為APB1的時鐘頻率,最大36MHz。
? ????????WDGTB為窗口看門狗的預分頻系數。
? ????????T[5:0]為窗口看門狗的計數器低6位。
通常不使用這個公式來計算溢出時間,因為當計數由最大值0X7F(或者用戶指定某個超過0X40的值)遞減到0X40(0011 1111)時,如果我們打開了提前喚醒中斷功能,那么這時就會產生一個中斷提醒我們應該喂狗了,于是重置初值,重新開始計數。因為計到0X40時可以產生中斷,所以不需要計算溢出時間以決定在多長時間內必須喂狗。當然,計算一下,心里了解多長時間必須喂狗也是可以的。
當遞減到0X40并且產生中斷喂狗時,必須在一個計數周期內完成喂狗,否則0X40再減1,就會啟動MCU復位,程序就會重啟。
(4)標號4:看門狗配置寄存器
這個就是喂狗時設置上窗口值,其值范圍就是0X7F到0X40之間
(5)標號5:系統復位信號
2.WWDG配置步驟
? 接下來我們介紹下如何使用庫函數對WWDG進行配置。這個也是在編寫程序中必須要了解的。具體步驟如下:(WWDG相關庫函數在stm32f10x_wwdg.c和stm32f10x_wwdg.h文件中)。
(1)使能WWDG時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
(2)設置WWDG窗口值和分頻數
void WWDG_SetWindowValue(uint8_t WindowValue);
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
分頻系數可以為WWDG_Prescaler_1、WWDG_Prescaler_2、WWDG_Prescaler_4、W
WDG_Prescaler_8。
(3)開啟WWDG中斷并分組??????????????????????????????
NVIC_Init();
WWDG_EnableIT();
(4)設置計數器初始值并使能WWDG???????????????????????????????
void WWDG_Enable(uint8_t Counter);
void WWDG_SetCounter(uint8_t Counter);
(5)編寫WWDG中斷服務函數
WWDG_IRQHandler
WWDG_ClearFlag();
3.硬件電路
? 由于WWDG是STM32內部資源,因此本硬件電路非常簡單,只有D1、D2指示燈連接,D1指示燈用來提示系統是否被復位,D2指示燈用來作為喂狗提示,每進入中斷喂狗D2指示燈狀態翻轉一次。
4.編寫窗口看門狗控制程序
? 本實驗所要實現的功能是:
用D1指示燈的先亮后滅,表示系統重啟了,系統每次重啟時D1指示燈點亮500ms時間,然后熄滅。
用D2指示燈不斷翻轉閃爍來表示正在喂狗。
程序框架如下:
(1)初始化WWDG(使能WWDG時鐘,設置窗口及分頻值,使能中斷等)
(2)編寫窗口看門狗中斷函數
(3)編寫主函數
main.c
#include "system.h"
#include "led.h"
#include "SysTick.h"
#include "wwdg.h"int main()
{SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷優先級分組LED_Init();led1=0;delay_ms(500);//LED1 如果沒有及時喂狗,LED就會熄滅500ms,提示系統重啟了WWDG_Init();while(1){led1=1;}
}
wwdg.c
#include "wwdg.h"
#include "led.h"
#include "SysTick.h"void WWDG_Init()
{NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); WWDG_SetPrescaler(WWDG_Prescaler_8);WWDG_SetWindowValue(0x5f);//只有在0x5F到0x40之間喂狗,系統才不會復位,不會重啟//設置中斷優先級,使能定時器中斷通道NVIC_InitStructure.NVIC_IRQChannel= WWDG_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);WWDG_Enable(0x7f);//設定計數器的初值,這里設的是最大值0x7fWWDG_ClearFlag();WWDG_EnableIT();}void WWDG_IRQHandler(void)
{//delay_ms(1);//用來檢查不喂狗時的情況WWDG_SetCounter(0x7f);WWDG_ClearFlag();led2=!led2;
}
程序燒寫到開發板上運行后是正常的,實驗成功!