1. 程式人生 > >STM32的IWDG(獨立看門狗)詳細用法

STM32的IWDG(獨立看門狗)詳細用法

文章出處:https://www.cnblogs.com/Liu-Jing/p/7243029.html

章參考資料:《STM32F4XX 中文參考手冊》IWDG 章節。

1、IWDG簡介:

 STM32 有兩個看門狗,一個是獨立看門狗另外一個是視窗看門狗,獨立看門狗號稱寵物狗,視窗看門狗號稱警犬,本章我們主要分析獨立看門狗的功能框圖和它的應用。獨立看門狗用通俗一點的話來解釋就是一個 12 位的遞減計數器,當計數器的值從某個值一直減到 0 的時候,系統就會產生一個復位訊號,即 IWDG_RESET。如果在計數沒減到 0 之前,重新整理了計數器的值的話,那麼就不會產生復位訊號,這個動作就是我們經常說的喂狗。看門狗功能由 VDD 電壓域供電,在停止模式和待機模式下仍能工作。

2 、IWDG功能框圖剖析

  ①獨立看門狗時鐘

獨立看門狗的時鐘由獨立的 RC振盪器 LSI提供,即使主時鐘發生故障它仍然有效,非常獨立。LSI的頻率一般在 30~60KHZ之間,根據溫度和工作場合會有一定的漂移,我們一般取 40KHZ,所以獨立看門狗的定時時間並一定非常精確,只適用於對時間精度要求比較低的場合。

②計數器時鐘

遞減計數器的時鐘由 LSI經過一個 8位的預分頻器得到,我們可以操作預分頻器暫存器 IWDG_PR 來設定分頻因子,分頻因子可以是:[4,8,16,32,64,128,256,256],計數器時鐘CK_CNT= 40/ 4*2^PRV,一個計數器時鐘計數器就減一。

③計數器

獨立看門狗的計數器是一個 12 位的遞減計數器,最大值為 0XFFF,當計數器減到 0時,會產生一個復位訊號:IWDG_RESET,讓程式重新啟動執行,如果在計數器減到 0 之前重新整理了計數器的值的話,就不會產生復位訊號,重新重新整理計數器值的這個動作我們俗稱喂狗。

④重灌載暫存器

重灌載暫存器是一個 12 位的暫存器,裡面裝著要重新整理到計數器的值,這個值的大小決定著獨立看門狗的溢位時間。超時時間 Tout = (4*2^prv) / 40 * rlv (s) ,prv是預分頻器暫存器的值,rlv是重灌載暫存器的值。

⑤鍵值暫存器

鍵值暫存器 IWDG_KR 可以說是獨立看門狗的一個控制暫存器,主要有三種控制方式,往這個暫存器寫入下面三個不同的值有不同的效果。

通過寫往鍵暫存器寫 0XCCC 來啟動看門狗是屬於軟體啟動的方式,一旦獨立看門狗啟動,它就關不掉,只有復位才能關掉。

⑥狀態暫存器

狀態暫存器 SR只有位 0:PVU和位 1:RVU有效,這兩位只能由硬體操作,軟體操作不了。RVU:看門狗計數器重灌載值更新,硬體置 1 表示重灌載值的更新正在進行中,更新完畢之後由硬體清 0。PVU: 看門狗預分頻值更新,硬體置’1’指示預分頻值的更新正在進行中,當更新完成後,由硬體清 0。所以只有當 RVU/PVU等於 0 的時候才可以更新重灌載暫存器/預分頻暫存器。

3、 怎麼用 IWDG

獨立看門狗一般用來檢測和解決由程式引起的故障,比如一個程式正常執行的時間是50ms,在執行完這個段程式之後緊接著進行喂狗,我們設定獨立看門狗的定時溢位時間為60ms,比我們需要監控的程式 50ms 多一點,如果超過 60ms 還沒有喂狗,那就說明我們監控的程式出故障了,跑飛了,那麼就會產生系統復位,讓程式重新執行。

4 、IWDG超時實驗

硬體設計:

1-IWDG,屬於內部資源,無需外部硬體
2-KEY 一個
3-LED 兩個,用開發板自帶的RGB燈即可

實驗設計

配置IWDG的超時時間為1S,如果在1S之內沒有及時喂狗的話,產生系統復位,並用LED燈的狀態變化來指示。

程式設計要點

1-如何配置IWDG的超時時間?
2-如果編寫喂狗函式?
3-在main函式裡面的什麼地方喂狗比較合適?

 配置IWDG的超時時間。

複製程式碼
/*
 * 設定 IWDG 的超時時間
 * Tout = prv/40 * rlv (s)
 *      prv可以是[4,8,16,32,64,128,256]
 * prv:預分頻器值,取值如下:
 *     @arg IWDG_Prescaler_4: IWDG prescaler set to 4
 *     @arg IWDG_Prescaler_8: IWDG prescaler set to 8
 *     @arg IWDG_Prescaler_16: IWDG prescaler set to 16
 *     @arg IWDG_Prescaler_32: IWDG prescaler set to 32
 *     @arg IWDG_Prescaler_64: IWDG prescaler set to 64
 *     @arg IWDG_Prescaler_128: IWDG prescaler set to 128
 *     @arg IWDG_Prescaler_256: IWDG prescaler set to 256
 *
 *        獨立看門狗使用LSI作為時鐘。
 *        LSI 的頻率一般在 30~60KHZ 之間,根據溫度和工作場合會有一定的漂移,我
 *        們一般取 40KHZ,所以獨立看門狗的定時時間並一定非常精確,只適用於對時間精度
 *        要求比較低的場合。
 *
 * rlv:重灌載暫存器的值,取值範圍為:0-0XFFF
 * 函式呼叫舉例:
 * IWDG_Config(IWDG_Prescaler_64 ,625);  // IWDG 1s 超時溢位 
 *                        (64/40)*625 = 1s
 */

void IWDG_Config(uint8_t prv ,uint16_t rlv)
{    
    // 使能 預分頻暫存器PR和重灌載暫存器RLR可寫
    IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable );
    
    // 設定預分頻器值
    IWDG_SetPrescaler( prv );
    
    // 設定重灌載暫存器值
    IWDG_SetReload( rlv );
    
    // 把重灌載暫存器的值放到計數器中
    IWDG_ReloadCounter();
    
    // 使能 IWDG
    IWDG_Enable();    
}
複製程式碼

喂狗函式:

複製程式碼
// 喂狗
void IWDG_Feed(void)
{
    // 把重灌載暫存器的值放到計數器中,喂狗,防止IWDG復位
    // 當計數器的值減到0的時候會產生系統復位
    IWDG_ReloadCounter();
}
複製程式碼複製程式碼
  
#include "stm32f4xx.h"
#include "./led/bsp_led.h"
#include "./key/bsp_key.h" 
#include "./iwdg/bsp_iwdg.h"


static void Delay(__IO u32 nCount); 


int main(void)
{
    /* LED 埠初始化 */
    LED_GPIO_Config();     
    
    Delay(0X8FFFFF);    

    /* 檢查是否為獨立看門狗復位 */
  if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
  {
    /* 獨立看門狗復位 */
    /*  亮紅燈 */
    LED_RED;

    /* 清除標誌 */
    RCC_ClearFlag();
        
        /*如果一直不喂狗,會一直復位,加上前面的延時,會看到紅燈閃爍
        在1s 時間內喂狗的話,則會持續亮綠燈*/
  }
  else
  {
    /*不是獨立看門狗復位(可能為上電覆位或者手動按鍵復位之類的) */
    /* 亮藍燈 */
    LED_BLUE;
  }        
  
  /*初始化按鍵*/
  Key_GPIO_Config();    
    
    // IWDG 1s 超時溢位
    IWDG_Config(IWDG_Prescaler_64 ,625); 
 
    //while部分是我們在專案中具體需要寫的程式碼,這部分的程式可以用獨立看門狗來監控
  //如果我們知道這部分程式碼的執行時間,比如是500ms,那麼我們可以設定獨立看門狗的
    //溢位時間是600ms,比500ms多一點,如果要被監控的程式沒有跑飛正常執行的話,那麼
    //執行完畢之後就會執行喂狗的程式,如果程式跑飛了那程式就會超時,到達不了喂狗的
    //程式,此時就會產生系統復位。但是也不排除程式跑飛了又跑回來了,剛好喂狗了,
    //歪打正著。所以要想更精確的監控程式,可以使用視窗看門狗,視窗看門狗規定必須
    //在規定的視窗時間內喂狗。
    while(1)                            
    {       
        if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON  )
        {
            // 喂狗,如果不喂狗,系統則會復位,復位後亮紅燈,如果在1s
            // 時間內準時喂狗的話,則會亮綠燈
            IWDG_Feed();        
            //喂狗後亮綠燈
            LED_GREEN;
        }
    }
}

static void Delay(__IO uint32_t nCount)     //簡單的延時函式
{
    for(; nCount != 0; nCount--);
}

/*********************************************END OF FILE**********************/
複製程式碼

程式先檢查是否為獨立看門狗復位,如果是獨立看門狗復位亮紅燈。如果一直不喂狗,會一直復位,加上前面的延時,會看到紅燈閃爍,在1S時間內喂狗的話,則會持續亮綠燈。