窗口看門狗

一,窗口看門狗介紹

獨立看門狗的喂狗範圍 0-X(X由預分頻器和重裝載值決定,最大值爲0xFFF)

獨立看門狗相關介紹:傳送門:獨立看門狗

相比於獨立看門狗,窗口看門狗限定了喂狗時間段(由喂狗上限和喂狗下限值限定的喂狗範圍) 
所以形象的稱作窗口看門狗


二,爲什麼需要窗口看門狗

獨立看門狗:在0-重載值之間任意時間都可以喂狗

     如果程序跑飛後又跑回正常
     或者跑亂的程序正好執行了刷新看門狗
     這樣獨立看門狗是不能檢查到並復位芯片的

窗口看門狗:限制了喂狗時間

    如果程序跑飛並且在限制的時間段喂狗是很困難的
    從而保證了程序的正常運行

三,獨立看門狗和窗口看門狗比較

獨立看門狗:

 驅動:由LSI驅動,即使主時鐘發生故障它仍有效

 適用場景:
      作爲主程序之外能夠完全獨立工作
      對時間精度要求較低

窗口看門狗:

 驅動:由APB1時鐘分頻後得到時鐘驅動

 適用場景:
      在精確計時窗口起作用的程序

四,獨立看門狗工作原理

  這裏寫圖片描述

參數:
     CNT:遞減計數器
     窗口上限:寄存器設置
     窗口下限:0x3F

隨時間推移,計數器值遞減,經過上窗口W和下窗口

     重載值->上窗口:這段時間不允許喂狗,如果喂狗會使芯片復位
     上窗口->下窗口:這段時間允許喂狗,下窗口位固定值(0x3F)
     下窗口:進入下窗口會產生復位

T6位:
     0x3F=00111111
     在計數器到達0x3F之前第六位爲1
     所以當計數器到達窗口下限前T6位爲1,到達窗口下限後T6位爲低電平

復位:
     當計數器到達窗口下限(喂狗失敗),會產生MCU復位信號,使芯片復位

五,窗口看門狗復位分析

這裏寫圖片描述

遞減計數器時鐘:
    時鐘來源PCLK1
    由於PCLK1時鐘頻率過高/4096
    再經過預分頻器WDGTB
    預分頻後作爲遞減計數器時鐘

WWDG_CR寄存器:
    T7:WDGA啓動位-使能窗口看門狗
    T0-6 :6位遞減計數器寄存器

WWDG_CFR寄存器:
    W0-6:設置窗口看門狗上窗口值

比較器:
    比較遞減計數器CNT和上窗口寄存器大小關係
    遞減計數器值>上窗口值  比較結果爲1

分析一: 計數器值>上窗口值時,喂狗,會產生復位 
  這裏寫圖片描述 
  

當計數器值>上窗口值時,比較器比較結果輸出爲1
此時喂狗,與門1下端輸入爲1
所以,或門1上端輸入爲1,導致與門2右端輸入爲1
此時看門狗處於使能狀態,與門2左端輸入爲1
所以芯片產生復位

分析二: 計數器值到達0x3F,會產生復位

  復位分析2

當計數器值到達0x3F時,T6位從1跳變到0
或門1下端輸入通過取反置1,所以或門1輸出值爲1,與門右側輸入值爲1
此時看門狗處於使能狀態,與門2左端輸入爲1
所以芯片產生復位

總結:窗口看門狗有兩種情況會產生復位

1,喂狗時間大於窗口上限值
2,計數器值從0x40減到0x3F

如果啓動看門狗並且允許中斷,當遞減計數器等於0x40時,會產生喚醒中斷EWI,它可以用於喂狗避免WWDG復位

窗口看門狗使用注意

上窗口值W[6:0]必須大於下窗口值0x40(0x40產生喚醒中斷),否則窗口看門狗就沒有窗口了

六,窗口看門狗的超時時間

  這裏寫圖片描述 
   
時鐘來源:

Fpclk1除以4096再經過WDGTB預分頻器
f = Fpclk1 / (4096 * 2^WDGTB)

超時時間:

窗口看門狗時鐘週期(時鐘頻率f分之1) 
t = 1/f * 看門狗計數器重載值

七,窗口看門狗相關寄存器

 WWDG_CR

直接寫WWDG_CR[6:0]實現喂狗
獨立看門狗喂狗:向鍵值寄存器IWDG_KR寫0xAAAA喂狗.將IWDG_RLR寄存器值重新裝載到計數器

 WWDG_CFR

 位0-6設置上窗口值
 位7-8設置時基-窗口看門狗的時鐘頻率
 位9提前喚醒中斷使能位(1:使能)當計數器到達0x40產生中斷

 WWDG_SR

 WWDG_SR只用到位0:提前喚醒中斷標誌
 當計數器達到0x40時,由硬件置1,需軟件清零

八,窗口看門狗相關庫函數

stm32f10x_wwdg.h中找到相關函數頭文件

/** @defgroup WWDG_Exported_Functions
  * @{
  */
void WWDG_DeInit(void);                          // 窗口看門狗復位
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler); // 設置預分頻係數-WWDG_CFR[8:7]
void WWDG_SetWindowValue(uint8_t WindowValue);   // 設置上窗口值-WWDG_CFR[6:0]
void WWDG_EnableIT(void);                        // 使能窗口看門狗中斷-提前喚醒中斷WWDG_CFR[9]
void WWDG_SetCounter(uint8_t Counter);          // 喂狗-重新寫WWDG_CR[6:0]
void WWDG_Enable(uint8_t Counter);               // 使能窗口看門狗並設置初值-WWDG_CR[7]+WWDG_CR[6:0]
FlagStatus WWDG_GetFlagStatus(void);             // 獲取WWDG_SR寄存器標誌位
void WWDG_ClearFlag(void);                       // 清除WWDG_SR寄存器標誌位
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

九,窗口看門狗相關配置步驟

// 1,使能看門狗時鐘:
    RCC_APB1PeriphClockCmd(); // 窗口看門狗時鐘來自APB1時鐘
// 2,設置分頻係數:
    WWDG_SetPrescaler();      // 確定窗口看門狗時鐘
// 3,設置上窗口值:
    WWDG_SetWindowValue();    // 設置上窗口值(下窗口值爲0x3F)
// 4,開啓提前喚醒中斷並設置中斷優先級:
    WWDG_EnableIT();          // 開啓提前喚醒中斷,當到達0x40時產生中斷,在中斷喂狗
    NVIC_Init();              // 使用中斷要NVIC初始化(先進行中斷優先級分組)
// 5,使能看門狗:
    WWDG_Enable();
// 6,喂狗:
    WWDG_SetCounter();
// 7,編寫中斷服務函數
    WWDG_IRQHandler();        // 在中斷中喂狗
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

十,窗口看門狗代碼:

HARDWARE/WDG目錄新建wgd.h

#ifndef __WDG_H
#define __WDG_H
#include "sys.h"                      // 用到了u8 u32

void WWDG_Init(u8 tr,u8 wr,u32 fprer);// 初始化WWDG
void WWDG_Set_Counter(u8 cnt);        // 設置WWDG的計數器 - 喂狗
void WWDG_NVIC_Init(void);            // 初始化窗口看門狗中斷優先級配置

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

HARDWARE/WDG目錄新建wgd.c

#include "wdg.h"
#include "led.h"

//WWDG計數器值,默認爲最大0x7F
u8 WWDG_CNT=0x7f;

//初始化窗口看門狗     
//  tr   : T[6:0],計數器值
//  wr   : W[6:0],窗口值
//  fprer: 分頻係數(WDGTB),僅最低2位有效
//  Fwwdg = PCLK1 / (4096 * 2^fprer).
void WWDG_Init(u8 tr, u8 wr, u32 fprer)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  // WWDG時鐘使能

    WWDG_CNT=tr&WWDG_CNT;             // 初始化WWDG_CNT (只取低7位,防止溢出)

    WWDG_SetPrescaler(fprer);         // 設置IWDG預分頻值

    WWDG_SetWindowValue(wr);          // 設置窗口值

    WWDG_Enable(WWDG_CNT);            // 設置看門狗使能位,並第一次喂狗               

    WWDG_ClearFlag();                 // 清除提前喚醒中斷標誌位

    WWDG_NVIC_Init();                 // 窗口看門狗中斷優先級設置

    WWDG_EnableIT();                  // 開啓窗口看門狗中斷
}

// 喂狗-重置WWDG計數器值
void WWDG_Set_Counter(u8 cnt)
{
    WWDG_Enable(cnt);        // 使能窗口看門狗並設置初值(首次喂狗)   
}

// 窗口看門狗中斷服務程序
void WWDG_NVIC_Init()
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;            // WWDG中斷
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  // 搶佔2,子優先級3,組2   
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         // 搶佔2,子優先級3,組2   
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;              // 使能
    NVIC_Init(&NVIC_InitStructure);                            // NVIC初始化
}

//計數器到達0x40時進入
void WWDG_IRQHandler(void)
{
    WWDG_SetCounter(WWDG_CNT);      // 註釋此句,窗口看門狗將產生復位

    WWDG_ClearFlag();               // 清除提前喚醒中斷標誌位

    LED1=!LED1;                     // LED1狀態翻轉 - 指示喂狗成功
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

USER/main.c主函數編寫


#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "wdg.h"


 int main(void)
 {       
    delay_init();          // 延時函數初始化

    // 設置中斷優先級分組爲組2:2位搶佔優先級,2位響應優先級    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    uart_init(115200);     // 串口初始化爲115200
    LED_Init();            // LED端口初始化
    KEY_Init();            // 按鍵初始化 

    LED0=0;                // LED0點亮
    delay_ms(300);         // 延時300ms

    // 計數器值爲7f,窗口寄存器爲5f,分頻數爲8
    WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);

    while(1)
    {
        LED0=1;            // LED0熄滅       
    }   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

以上程序實現:

程序初始化LED點亮延時300ms熄滅
窗口看門狗從0x7F開始遞減計數,上窗口爲0x5F,下窗口爲0x3F
計數器到達0x40進入提前喚醒中斷,
在中斷函數中進行喂狗操作,計數器翻轉(從0x7F重新計數),LED1翻轉
以此循環...
翻轉頻率爲從0x7F計數到0x40,翻轉時間可以根據公式計算

正常喂狗:
     LED0亮300ms之後熄滅,LED1不斷閃爍

喂狗失敗(註釋掉喂狗函數):
     程序不斷復位,LED0閃爍
發佈了11 篇原創文章 · 獲贊 38 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章