1. 程式人生 > >【stm32f407】獨立看門狗 iwdog

【stm32f407】獨立看門狗 iwdog

一.獨立看門狗

STM32F4的獨立看門狗由內部專門的32Khz低速時鐘(LSI)驅動,即使主時鐘發生故障,它也仍然有效。這裡需要注意獨立看門狗的時鐘是一個內部RC時鐘,所以並不是準確的32Khz,而是在15~47Khz之間的一個可變化的時鐘,只是我們在估算的時候,以32Khz的頻率來計算,看門狗對時間的要求不是很精確,所以,時鐘有些偏差,都是可以接受的。獨立看門狗有幾個暫存器與我們這節相關,我們分別介紹這幾個暫存器,首先是關鍵字暫存器IWDG_KR

      

在關鍵字暫存器(IWDG_KR)中寫入0xCCCC,開始啟用獨立看門狗;此時計數器開始從其

復位值0xFFF遞減計數。當計數器計數到末尾

0x000時,會產生一個復位訊號(IWDG_RESET)

無論何時,只要關鍵字暫存器IWDG_KR中被寫入0xAAAA IWDG_RLR中的值就會被重新

載入到計數器中從而避免產生看門狗復位 。IWDG_PR IWDG_RLR 暫存器具有防寫功能。要修改這兩個暫存器的值,必須先向IWDG_KR暫存器中寫入0x5555。將其他值寫入這個暫存器將會打亂操作順序,暫存器將重新被保護。重灌載操作(即寫入0xAAAA)也會啟動防寫功能。 接下來,我們介紹預分頻暫存器(IWDG_PR),該暫存器用來設定看門狗時鐘的分頻係數,最低為4,最高位256,該暫存器是一個32位的暫存器,但是我們只用了最低3位,其他都是保留位,預分頻暫存器如下:

在介紹完IWDG_PR之後,我們介紹一下重灌載暫存器IWDG_RLR。該暫存器用來儲存重

裝載到計數器中的值。該暫存器也是一個32位暫存器,但是隻有低12位是有效的,如圖

只要對以上三個暫存器進行相應的設定,我們就可以啟動STM32F4的獨立看門狗。獨立

看門狗相關的庫函式操作函式在檔案stm32f4xx_iwdg.c和對應的標頭檔案stm32f4xx_iwdg.h

二.獨立看門狗應用

1)取消暫存器防寫(向IWDG_KR寫入0X5555

通過這步,我們取消IWDG_PRIWDG_RLR的防寫,使後面可以操作這兩個暫存器,設定IWDG_PRIWDG_RLR的值。這在庫函式中的實現函式是:

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

這個函式非常簡單,顧名思義就是開啟/取消防寫,也就是使能/失能寫許可權。

2)設定獨立看門狗的預分頻係數和重灌載值設定看門狗的分頻係數的函式是:

voidIWDG_SetPrescaler(uint8_t IWDG_Prescaler); //設定IWDG預分頻值

設定看門狗的重灌載值的函式是:

voidIWDG_SetReload(uint16_t Reload); //設定IWDG重灌載值

設定好看門狗的分頻係數prer和重灌載值就可以知道看門狗的喂狗時間(也就是看門狗溢位時間),該時間的計算方式為:

Tout=((4×2^prer)×rlr) /40

其中Tout為看門狗溢位時間(單位為ms);prer為看門狗時鐘預分頻值(IWDG_PR值 )範圍為0~7rlr為看門狗的重灌載值(IWDG_RLR的值);

比如我們設定prer值為4rlr值為625,那麼就可以得到Tout=64×625/40=1000ms,這樣,看門狗的溢位時間就是1s,只要你在一秒鐘之內,有一次寫入0XAAAAIWDG_KR,就不會導致看門狗復位(當然寫入多次也是可以的)。這裡需要提醒大家的是,看門狗的時鐘不是準確的40Khz,所以在喂狗的時候,最好不要太晚了,否則,有可能發生看門狗復位。

3)過載計數值喂狗(向IWDG_KR寫入0XAAAA

庫函式裡面過載計數值的函式是:

IWDG_ReloadCounter();//按照IWDG重灌載暫存器的值重灌載IWDG計數器

通過這句,將使STM32重新載入IWDG_RLR的值到看門狗計數器裡面。即實現獨立看門狗的喂狗操作。

4) 啟動看門狗(IWDG_KR寫入0XCCCC)

庫函式裡面啟動獨立看門狗的函式是:

IWDG_Enable();//使能IWDG

通過這句,來啟動STM32F4的看門狗。注意IWDG在一旦啟用,就不能再被關閉!想要關閉,只能重啟,並且重啟之後不能開啟IWDG,否則問題依舊,所以在這裡提醒大家,如果不用IWDG的話,就不要去開啟它,免得麻煩。

通過上面4個步驟,我們就可以啟動STM32F4的看門狗了,使能了看門狗,在程式裡面就必須間隔一定時間喂狗,否則將導致程式復位。利用這一點,我們本章將通過一個LED燈來指示程式是否重啟,來驗證STM32F4的獨立看門狗。

在配置看門狗後,DS0將常亮,如果KEY_UP按鍵按下,就喂狗,只要KEY_UP不停的按,看門狗就一直不會產生復位,保持DS0的常亮,一旦超過看門狗定溢位時間(Tout)還沒按,那麼將會導致程式重啟,這將導致DS0熄滅一次。

三.原始碼

Iwdog.h

#ifndef_IWDOG_H_H_H
#define_IWDOG_H_H_H
#include"stm32f4xx_iwdg.h"
voidIWDG_Init(u8 prer,u16 rlr);//IWDG初始化
voidIWDG_Feed(void);  //喂狗函式
#endif

Iwdog.c

#include"iwdog.h" 
voidIWDG_Init(u8 prer,u16 rlr)
{
  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//使能對IWDG->PR IWDG->RLR的寫
       
  IWDG_SetPrescaler(prer); //設定IWDG分頻係數
 
  IWDG_SetReload(rlr);   //設定IWDG裝載值
 
  IWDG_ReloadCounter(); //reload
       
  IWDG_Enable();       //使能看門狗
}
 
voidIWDG_Feed(void)
{
  IWDG_ReloadCounter();//reload
}

Main.c

#include"led.h"
#include"key.h"
#include"delay.h"
#include"uart.h"
#include"exit.h"
#include"iwdog.h"
voidUser_Delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}
staticint count = 0;
intmain(void)
{
 
#if 1
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設定系統中斷優先順序分組2
  delay_init(168);  //初始化延時函式
  LED_Init();                        //初始化LED埠
  KEY_Init();                //初始化按鍵
  delay_ms(100);    //延時100ms 
  IWDG_Init(4,500); //與分頻數為64,過載值為500,溢位時間為1s
  
  LED_Operate(LED_GREEN,LED_ON);
  
  while(1)
  {
    if(KEY_Scan() == KEY_ON)
    {
      IWDG_Feed();//喂狗
    }
    delay_ms(10);
  }
#endif
   
}