STM32的兩隻狗兒——窗口看門狗

STM32窗口看門狗共三個寄存器,以下圖:web

看似簡單,但設置及應用起來有很多玄機。函數

 

控制寄存器(WWDG_CR)中的值必須在0xFF0xC0之間, 由於它的第0至第6位爲遞減計數器CNT,在它的第6位變爲0時將產生復位,因此在初始化時須要爲1,第7WDGA是用來設置啓動或禁止窗口看門狗的,當爲1進纔會啓動窗口看門狗,因此第6和第7位都需爲1,即WWDG_CR 的值須要大於等於0xC0 spa

 

配置寄存器(WWDG_CFR) 0至第6 是設置窗口邊界值用的,只有當遞減計數器CNT的值小於邊界值時才能夠喂狗,過早不行,狗還不餓,撐死了。而且7位遞減計數器CNT減小到0x3F時即T6位變爲0,此時MCU也會復位,過晚了,狗餓死了。因此必須在指定的時間範圍喂狗,過早或過晚都將產生復位,而這樣設計能夠減小軟件跑飛了卻仍可以歪打正着地喂狗的發生機率。設計

       

狀態寄存器(WWDG_CFR) 只用到了第0位,EWIF(Early wakeup interrupt flag )是提早喚醒中斷標識,當遞減計數器CNT的值到達0X40(若再減小一次則T6位變爲0,產生復位)時此位由硬件置1,且需用軟件清0,注意不管中斷是否使能此位都會被硬件置1。而提早喚醒中斷使能設置是在配置寄存器(WWDG_CFR)9EWI(Early wakeup interrupt),此位需由軟件置1,則會在當遞減計數器CNT的值到達0X40時產生中斷,而且與EWIF不一樣,此位是由硬件清0code

 

另外控制寄存器(WWDG_CR)中第7WDGA(Activation bit)激活位,需用軟件來置1,以啓動窗口看門狗,而且一旦啓動後,只能在復位或重啓後由硬件來清0。配置寄存器(WWDG_CFR)的第8位和第7WDGTB[1:0]用來設置時基(Timer base)預分頻數。orm

 

以上描述可參考下圖以更清晰的理解:ip

 

窗口看門狗應用時還要注意算準最小與最大喂狗時間,以便正確地喂狗,以下:ci

 

PCLK1頻率爲36MHz 時,則資源

上窗口時間:T_min = 4096 * (2^WDGTB)*(WWDG_CR[6:0] - WWDG_CFR[6:0])/36 (us)it

下窗口時間: T_max = 4096 * (2^WDGTB)*(WWDG_CR[6:0] - 0x40)/36 (us) 

喂狗動做需在這段時間之間進行,而喂狗動做爲向控制寄存器(WWDG_CR)中寫值,值的範圍上文已經說過。

窗口看門狗中斷函數void WWDG_IRQHandler(void);是用來作什麼的呢。窗口看門狗中斷函數是在遞減計數器減小到0x40是被調用,由於它自己計數就比較慢,因此離數到0x3F復位還有一段時間,我認爲這樣設計是爲MCU復位以前留下一點時間,可以使工程設計人員根據須要在中斷函數保存一些重要的數據,這樣在復位後MCU可知道系統因異常復位的某此狀態,以使系統有更高穩定性。

而且我以爲在窗口看門狗中斷函數中喂狗沒有什麼意義,程序原本已經不按正常運行了,還在中斷函數中喂狗防止復位只會錯上加錯,很差好利用它乾點正事, 更是浪費資源。

這點上我我的認爲不要被點原子示例代碼誤導哦,但其仍是有部分借鑑意義的,如下爲初始化相關代碼:

  //窗口看門狗中斷服務設置程序

    void WWDG_NVIC_Init()
    {
      NVIC_InitTypeDef NVIC_InitStructure;
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);      
      NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;       //WWDG 中斷
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //搶佔2 子優先級3 組2
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    //搶佔2,子優先級3,組2
      NVIC_Init(&NVIC_InitStructure);                       //NVIC 初始化
    }

 

 

 //保存WWDG 計數器的設置值,默認爲最大.

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.
      WWDG_SetPrescaler(fprer);        //設置IWDG 預分頻值
      WWDG_SetWindowValue(wr);       //設置窗口值
      WWDG_Enable(WWDG_CNT);       //使能看門狗,設置counter
      WWDG_ClearFlag();               //清除提早喚醒中斷標誌位 (注:若沒有此句則會在初始化後先進入中斷一次)
      WWDG_NVIC_Init();               //初始化窗口看門狗NVIC
      WWDG_EnableIT();                //開啓窗口看門狗中斷
}


以上代碼朋友們也能夠跳到庫函數代碼中本身研究下,另外要說明下的是WWDG_EnableIT(); 函數相關代碼

#define CFR_EWI_BB        (PERIPH_BB_BASE + (CFR_OFFSET * 32) + (EWI_BitNumber * 4))


用到位帶操做,具體理解可參照《Cortex-M3權威指南》第五章的位帶操做相關介紹(具體89)



相關文章
相關標籤/搜索