STM32-独立看门狗原理-实验
獨立看門狗原理概述
為什么要看門狗:
在由單片機構成的微型計算機系統中,由于單片機的工作常常會受到來自外界電磁場的干擾,造成程序的跑飛,而陷入死循環(huán),程序的正常運行被打斷,由單片機控制的系統無法繼續(xù)工作,會造成整個系統的陷入停滯狀態(tài),發(fā)生不可預料的后果,所以出于對單片機運行狀態(tài)進行實時監(jiān)測的考慮,便產生了一種專門用于監(jiān)測單片機程序運行狀態(tài)的模塊或者芯片,俗稱“看門狗”(watchdog) 。
看門狗解決的問題是什么:
在啟動正常運行的時候,系統不能復位
在系統跑飛(程序異常執(zhí)行)的情況,使系統復位,程序重新執(zhí)行
獨立看門狗概述:
STM32內置兩個看門狗:獨立看門狗和窗口看門狗。
兩個看門狗提供了更高的安全性,時間的精確性和使用的靈活性。
兩個看門狗設備(獨立看門狗/窗口看門狗)可以用來檢測和 解決由軟件錯誤引起的故障。當計數器達到給定的超時值時,觸發(fā)一個中斷(僅適用窗口看門狗)或者產生系統復位。
獨立看門狗(IWDG)由專用的低速時鐘(LSI)驅動,即使主時鐘發(fā)生故障它仍有效。
獨立看門狗適合應用于需要看門狗作為一個在主程序之外 能夠完全獨立工作,并且對時間精度要求低的場合。
窗口看門狗由從APB1時鐘分頻后得到時鐘驅動。通過可配置的時間窗口來檢測應用程序非正常的過遲或過早操作.窗口看門狗最適合那些要求看門狗在精確計時窗口起作用的程序。
M7的獨立看門狗還可以配置做窗口看門狗使用。
因為M7本身帶了窗口看門狗,所以一般情況下,我們都比較少使用此功能。
獨立看門狗工作原理描述
在鍵值寄存器(IWDG_KR)中寫入0xCCCC,開始啟用獨立看門狗。此時計數器開始從其復位值0xFFF遞減,當計數器值計數到尾值0x000時會產生一個復位信號(IWDG_RESET)。
無論何時,只要在鍵值寄存器IWDG_KR中寫入0xAAAA(通常說的喂狗), 自動重裝載寄存器IWDG_RLR的值就會重新加載到計數器,從而避免看門狗復位。
如果程序異常,就無法正常喂狗,從而系統復位。
獨立看門狗框圖
時鐘來自于LSI,經過分頻,產生一個時鐘,進入12位遞減計數器。首先在鍵寄存器中寫入0xcccc,那么就開始從初值開始計數,如果說鍵寄存器中寫入0xaaaa,那么就把RLR寄存器中的值重新加載到計數器。當程序不正常喂狗的時候,就會一直減到零,然后產生復位信號。
獨立看門狗超時時間
溢出時間計算:
Tout=((4×2^prer) ×rlr) /32 (M4)
32 /(4×2^ prer)就是經過分頻后的頻率。其中prer是設置的PR[2:0]位,然后倒過來就是周期,那么溢出時間就是((4×2^ prer) ×rlr) /32,其中rlr是重裝載寄存器的值。
時鐘頻率LSI=32K, 一個看門狗時鐘周期就是最短超時時間。
最長超時時間= (IWDG_RLR寄存器最大值)X看門狗時鐘周期.
舉個例:如果說要把看門狗溢出時間設置為1s,首先由于時鐘頻率LSI=32k,如果說預分頻是64,那么LSI/64=0.5khz,也就是說可以設置rlr的值為500,這樣的話溢出時間就是1s。注意重裝載寄存器rlr的最大值是2^12-1,不能大于它。
獨立看門狗寄存器
IWDG_KR:鍵值寄存器,0~15位有效
IWDG_PR:預分頻寄存器,0~2位有效。具有寫保護功能,要操作先取消寫保護
IWDG_RLR:重裝載寄存器,0~11位有效。具有寫保護功能,要操作先取消寫保護。
IWDG_SR:狀態(tài)寄存器,0~1位有效
鍵值寄存器:IWDG_KR
KEY[15:0]:鍵值 (Key value)(只能寫,讀為 0x0000)
必須每隔一段時間便通過軟件對這些位寫入鍵值 0xAAAA,否則當計數器計數到 0 時,看門狗會產生復位。
寫入鍵值 0x5555 可使能對 IWDG_PR、IWDG_RLR 和 IWDG_WINR 寄存器的訪問
寫入鍵值 0xCCCC可啟動看門狗(選中硬件看門狗選項的情況除外)
預分頻寄存器:IWDG_PR
位 2:0 PR[2:0]:預分頻系數 (Prescaler divider)
這些位受寫訪問保護。通過軟件設置這些位來選擇計數器時鐘的預分頻因子。若要更改預分頻器的分頻系數,IWDG_SR 的 PVU 位必須為 0。
000:4 分頻
001:8 分頻
010:16 分頻
011:32 分頻
100:64 分頻
101:128 分頻
110:256 分頻
111:256 分頻
重裝載寄存器:IWDG_RLR
位 11:0 RL[11:0]:看門狗計數器重載值 (Watchdog counter reload value)
這些位受寫訪問保護。這個值由軟件設置,每次對 IWDG_KR 寄存器寫入值 0xAAAA 時,這個值就會重裝載到看門狗計數器中。之后,看門狗計數器便從該裝載的值開始遞減計數。超時周期由該值和時鐘預分頻器共同決定。
若要更改重載值,IWDG_SR 中的 RVU 位必須為 0
狀態(tài)寄存器:IWDG_SR
位 31:3 保留,必須保持復位值。
位 2 WVU:看門狗計數器窗口值更新 (Watchdog counter window value update) 可通過硬件將該位置 1 以指示窗口值正在更新。當在 VDD 電壓域下完成重載值更新操作后(需 要多達 5 個 RC 40 kHz 周期),會通過硬件將該位復位。 窗口值只有在 WVU 位為 0 時才可更新。 此位只有在通用“窗口”= 1 時才生成。
位 1 RVU:看門狗計數器重載值更新 (Watchdog counter reload value update) 可通過硬件將該位置 1 以指示重載值正在更新。當在 VDD 電壓域下完成重載值更新操作后(需 要多達 5 個 RC 40 kHz 周期),會通過硬件將該位復位。 重載值只有在 RVU 位為 0 時才可更新。
位 0 PVU:看門狗預分頻器值更新 (Watchdog prescaler value update) 可通過硬件將該位置 1 以指示預分頻器值正在更新。當在 VDD 電壓域下完成預分頻器值更新操 作后(需要多達 5 個 RC 40 kHz 周期),會通過硬件將該位復位。 預分頻器值只有在 PVU 位為 0 時才可更新。
IWDG獨立看門狗操作HAL庫函數
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);獨立看門狗的初始化函數
找到參數的定義:可以發(fā)現和其他外設的句柄類似。第一個成員變量是外設的基地址。
typedef struct {IWDG_TypeDef *Instance; /*!< Register base address */ IWDG_InitTypeDef Init; /*!< IWDG required parameters */HAL_LockTypeDef Lock; /*!< IWDG Locking object */__IO HAL_IWDG_StateTypeDef State; /*!< IWDG communication state */ }IWDG_HandleTypeDef;然后找到第二個變量IWDG_InitTypeDef的定義:Prescaler配置的是預分頻系數,Reload配置的是重裝載值。
typedef struct {uint32_t Prescaler; /*!< Select the prescaler of the IWDG. This parameter can be a value of @ref IWDG_Prescaler */uint32_t Reload; /*!< Specifies the IWDG down-counter reload value. This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */ }IWDG_InitTypeDef;void HAL_IWDG_MspInit(IWDG_HandleTypeDef *hiwdg);初始化回調函數
HAL_StatusTypeDef HAL_IWDG_Start(IWDG_HandleTypeDef *hiwdg);啟動獨立看門狗
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);喂狗
獨立看門狗操作步驟
1.初始化看門狗:預分頻系數,重裝載值。
HAL_IWDG_Init();
該函數在操作PR和RLR寄存器之前會取消寫保護。
2.啟動看門狗
HAL_IWDG_Start();
3.喂狗:
HAL_IWDG_Refresh();
獨立看門狗實驗
初始化看門狗
如何寫,首先看文件里面的函數都有啥,然后找參數,然后調函數。
根據步驟1調用HAL_IWDG_Init函數:
首先找到HAL_IWDG_Init獨立看門狗的初始化函數:
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg) {/* Check the IWDG handle allocation */if(hiwdg == NULL){return HAL_ERROR;}/* Check the parameters */assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload)); if(hiwdg->State == HAL_IWDG_STATE_RESET){ /* Allocate lock resource and initialize it */hiwdg->Lock = HAL_UNLOCKED;/* Init the low level hardware */HAL_IWDG_MspInit(hiwdg);}/* Change IWDG peripheral state */hiwdg->State = HAL_IWDG_STATE_BUSY; /* Enable write access to IWDG_PR and IWDG_RLR registers */ IWDG_ENABLE_WRITE_ACCESS(hiwdg);/* Write to IWDG registers the IWDG_Prescaler & IWDG_Reload values to work with */MODIFY_REG(hiwdg->Instance->PR, IWDG_PR_PR, hiwdg->Init.Prescaler);MODIFY_REG(hiwdg->Instance->RLR, IWDG_RLR_RL, hiwdg->Init.Reload);/* Change IWDG peripheral state */hiwdg->State = HAL_IWDG_STATE_READY;/* Return function status */return HAL_OK; }現在知道參數是個結構體,然后在main里面寫:
IWDG_HandleTypeDef iwdg_handler;
HAL_IWDG_Init(&iwdg_handler);
然后開始對iwdg_handler的參數進行設置,可以首先看到HAL_IWDG_Init函數中,有對IWDG_HandleTypeDef類型操作的函數。那我們可以找到這個函數的定義。
assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));IS_IWDG_ALL_INSTANCE定義如下:
#define IS_IWDG_ALL_INSTANCE(INSTANCE) ((INSTANCE) == IWDG)所以說就知道了INSTANCE應該被設置為IWDG。這就叫做有效性判斷。
所以main中寫: iwdg_handler.Instance = IWDG;
所以一個成員變量就設置好了,同理設置其他的變量。
可以找到Prescaler相關的定義,然后可以在main中寫
iwdg_handler.Init.Prescaler = IWDG_PRESCALER_64;
#define IS_IWDG_PRESCALER(__PRESCALER__) (((__PRESCALER__) == IWDG_PRESCALER_4) || \((__PRESCALER__) == IWDG_PRESCALER_8) || \((__PRESCALER__) == IWDG_PRESCALER_16) || \((__PRESCALER__) == IWDG_PRESCALER_32) || \((__PRESCALER__) == IWDG_PRESCALER_64) || \((__PRESCALER__) == IWDG_PRESCALER_128)|| \((__PRESCALER__) == IWDG_PRESCALER_256))如果說要把看門狗溢出時間設置為1s,首先由于時鐘頻率LSI=32k,如果說預分頻是64,那么LSI/64=0.5khz,也就是說可以設置rlr的值為500,這樣的話溢出時間就是1s。
iwdg_handler.Init.Reload = 500;
啟動看門狗
然后開始調用HAL_IWDG_Start函數。
? HAL_IWDG_Start(&iwdg_handler);
喂狗
HAL_IWDG_Refresh(&iwdg_handler);//喂狗
main代碼:
系統復位后按鍵一直沒有按下(喂狗),一旦到了溢出時間(1s),就會產生復位。系統如果復位,led燈會熄滅,系統初始化時候是led燈亮,所以說如果一直不按按鍵,那么系統的led燈會一閃一閃。
如果說按下按鍵,也就是說喂狗的周期小于溢出時間的話,那么程序就不會復位了,那么led燈就常亮了,這是因為在while執(zhí)行之前初始化led燈是亮的,如果一直喂狗的話程序就一直在while循環(huán)里執(zhí)行。
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "key.h" #include "exti.h"IWDG_HandleTypeDef iwdg_handler;int main(void) {HAL_Init(); //初始化HAL庫 Stm32_Clock_Init(360,25,2,8); //設置時鐘,180Mhzdelay_init(180); //初始化延時函數uart_init(115200); //初始化USARTLED_Init(); //初始化LED EXTI_Init();delay_ms(100);iwdg_handler.Instance = IWDG;iwdg_handler.Init.Prescaler = IWDG_PRESCALER_64;iwdg_handler.Init.Reload = 500;HAL_IWDG_Init(&iwdg_handler);HAL_IWDG_Start(&iwdg_handler);LED0=0;while(1){if(KEY_Scan(0)==WK_UP)//檢測WK_UP按鍵是否按下{HAL_IWDG_Refresh(&iwdg_handler);//喂狗delay_ms(10);}} }總結
以上是生活随笔為你收集整理的STM32-独立看门狗原理-实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每个java小应用程序都得继承,JAVA
- 下一篇: 燃气灶电气线路图及原理_一位造价大神的电