1. 程式人生 > >STM32的看門狗了解及代碼演示

STM32的看門狗了解及代碼演示

clear tle 最小值 就會 del size 概念 channels gpio

一、介紹:

STM32看門狗分為獨立看門狗和窗口看門狗兩種,其兩者使用調條件如下所示,

技術分享圖片

IWDG和WWDG兩者特點如下圖所示:

技術分享圖片

獨立看門狗的手冊資料:

技術分享圖片

串口看門狗的手冊資料:

技術分享圖片

應當註意:在窗口看門狗中,當遞減計數器在窗口外被重新裝載,(若看門狗被啟動)則產生復位

由於窗口看門狗使用的APB1的PCLK1,時鐘最高36MHZ,和RCC_APB2Periph_GPIOx不同,APB1最大就是36MHZ,APB2最大就是72MHZ。

所以串口看門狗需要配置APB1時鐘使能,如下語句。

可以從圖1-3 窗口看門狗編程說明紅看到TWWDG=TPCLK1 x 4096 x 2^WDGTB x (T[5:0]+1) ; (ms)

WDGTB[1:0]: 時基 (Timer base),也就是設置WDGTB 的值是1/2/4還是8,這在配置寄存器(WWDG_CFR)寄存器的位8:7 中設置,

其預分頻器的時基可以設置如下:

00: CK計時器時鐘(PCLK1除以4096)除以1

01: CK計時器時鐘(PCLK1除以4096)除以2

10: CK計時器時鐘(PCLK1除以4096)除以4

11: CK計時器時鐘(PCLK1除以4096)除以8

也可以直接用這個函數

1 WWDG_SetPrescaler(WWDG_Prescaler_8); //8預分頻,則WWDG時鐘頻率=(PCK1(36M)/4096)/8=1099Hz(910us)

也可以直接用這個函數

其次是設置窗口值,用來與遞減計數器進行比較用的窗口值。通過如下函數即可

1  WWDG_SetWindowValue(80);//設置窗口值為80則WWDG的計數值必須在64~80之間才能餵狗(64是0x40,當再次減1就會T6清零,從而導致復位了,即刷新窗口設置成了80-64,127-80也是不能更新值得否則也會復位

應當註意:在窗口看門狗中,當遞減計數器在窗口外被重新裝載,(若看門狗被啟動)則產生復位,也即是說在90-64外面使用這個重載函數,會有問題發生

最後我們設置 (T[5:0]+1)的值,這裏我們設置最大127,代碼如下,以後每次餵狗也可以用這個函數進行重載計數值(餵狗)。

1 WWDG_Enable(127
)

因為這是會導致產生復位,所以重載的窗口一定要設置好。

總結就是我們使用串口看門狗應該先配置寄存器(WWDG_CFR),即配置窗口值是多少到x40(我們設置的80-0x40),這個配置會告訴單片機什麽時候來與遞減計數器進行值比較,如果值小於0x40就產生復位。

當然,如果你在減減計數值還在0x7E-0x50(127-80)之間就重載計數值(餵狗)同樣會導致芯片復位。所以窗口的概念一定要理解好,在窗內才可以重載計數值(餵狗),這樣才不會莫名被復位。

二、代碼實現

最終的初始化窗口看門狗的配置函數(WWDG)如下:

/*************************************************************
Function : WWDGReste_Init
Description: 窗口看門狗定時器
Input : none
return : none
*************************************************************/
void WWDGReste_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);//WWDG連接在PCLK1(36M)的時鐘線上

    WWDG_SetPrescaler(WWDG_Prescaler_8); //8預分頻,則WWDG時鐘頻率=(PCK1(36M)/4096)/8=1099Hz(910us)
    WWDG_SetWindowValue(80);//設置窗口值為80則WWDG的計數值必須在64~80之間才能餵狗(64是0x40,當再次減1就會T6清零,從而導致復位了)
    //設置WWDG計數值為127,超時時間=910us*64=58.25ms,所以
    WWDG_Enable(127);//(0x7F為設置的最小值,0x40為最大的復位值,取值應該在0x40~0x7F之間)刷新窗口為:910us*(127-80)=42.77ms < 刷新窗口 < 910us*64=58.25ms
}

主函數如下:

void mian(void)
{
//初始化
    while(1)
    {
        delay_ms(400)
        WWDG_Enable(127);
      //無需判斷直接等待窗口看門狗中斷觸發
    }
}  

或者這樣的留參帶使能中斷形式:

#include "wdg.h"
#include "stm32f10x_wwdg.h"



static u8 WWDG_CNT=0x7f;     /*保存WWDG計數器的設置值,默認為最大127. */

//========================================================================================
/**
 * 初始化窗口看門狗
 * tr :T[6:0],計數器值
 * wr :W[6:0],窗口值
 * fprer:分頻系數(WDGTB),僅最低2位有效
 * Fwwdg=PCLK1/(4096*2^fprer).
 // 計數器值為7f,窗口寄存器為5f,分頻數為8
    WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);
 */
void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);    /*WWDG時鐘使能*/
    WWDG_SetPrescaler(fprer); /*設置IWDG預分頻值*/
    WWDG_SetWindowValue(wr);    /*設置窗口值*/
    WWDG_CNT=tr&WWDG_CNT; /* 初始化WWDG_CNT. */
    WWDG_Enable(WWDG_CNT);    /*使能看門狗 ,    設置 counter . */
    WWDG_ClearFlag();    /*清除提前喚醒中斷標誌位*/
    WWDG_NVIC_Init();/* 初始化窗口看門狗 NVIC */
    WWDG_EnableIT(); /* 開啟窗口看門狗中斷 */
}

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

/**
 * 重設置WWDG計數器的值,餵狗
 */
void WWDG_Set_Counter(u8 cnt)
{
    WWDG_Enable(cnt); /*使能看門狗 ,    設置 counter .    */
}

/**
 * 看門狗中斷服務程序
 */
void WWDG_IRQHandler(void)
{
    WWDG_Set_Counter(WWDG_CNT);
    WWDG_ClearFlag();    /*清除提前喚醒中斷標誌位*/
    LED1 = ~LED1;         /*LED狀態翻轉 */
}

void mian(void)
{
//初始化
    while(1)
    {
    
    }
}

附錄:

獨立看門狗(IWDG)的代碼:

/**
 * 初始化獨立看門狗
 * prer:分頻數:0~7(只有低 3 位有效!)
 * 分頻因子=4*2^prer.但最大值只能是 256!
 * rlr:重裝載寄存器值:低 11 位有效.
 * 時間計算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
 *IWDG_Init(4,625);//初始化獨立看門狗,分頻數為64,重裝載值為625,溢出時間計算為:64*625/40=1000ms=1s
 */
void IWDG_Init(u8 prer,u16 rlr)
{
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* 使能對寄存器IWDG_PR和IWDG_RLR的寫操作*/
    IWDG_SetPrescaler(prer);    /*設置IWDG預分頻值:設置IWDG預分頻值*/
    IWDG_SetReload(rlr);     /*設置IWDG重裝載值*/
    IWDG_ReloadCounter();    /*按照IWDG重裝載寄存器的值重裝載IWDG計數器*/
    IWDG_Enable();        /*使能IWDG*/
}

/**
 * 餵獨立看門狗
 */
void IWDG_Feed(void)
{
    IWDG_ReloadCounter();    /*reload*/
}

/**
 *main函數
 */
void main(void)
{
  NVIC_Configuration();//優先級配置
  IWDG_Init(4,625);//初始化獨立看門狗,分頻數為64,重裝載值為625,溢出時間計算為:64*625/40=1000ms=1s
 while(1)
  {
    delay_ms(500);//0.5秒餵一次狗
      IWDG_Feed();//餵狗
  }        
}

STM32的看門狗了解及代碼演示