STM32F103五分钟入门系列(十三)独立看门狗IWDG
參考:STM32F103五分鐘入門系列(十三)獨立看門狗IWDG
作者:自信且愛笑‘
發布時間:2021-07-31 19:50:28
網址:https://blog.csdn.net/Curnane0_0/article/details/119269391?utm_source=app&app_version=4.12.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
參考:STM32 獨立看門狗實驗
作者:追兮兮
發布時間: 2020-12-25 10:14:21
網址:https://blog.csdn.net/weixin_44234294/article/details/111661281
學習板:STM32F103ZET6
獨立看門狗
- 一、獨立看門狗(IWDG)簡介
- 1、什么是看門狗
- 2、獨立看門狗應用場合
- 二、獨立看門狗時鐘
- 三、獨立看門狗的相關寄存器
- (1)鍵寄存器(IWDG_KR)
- (2)預分頻寄存器(IWDG_PR)
- (3)重裝載寄存器(IWDG_RLR)
- (4)狀態寄存器(IWDG_SR)
- 四、獨立看門狗編程順序
- 五、例子(寄存器版)
- 六、獨立看門狗常用庫函數
- (1)取消PR、RLR寄存器寫保護函數IWDG_WriteAccessCmd()
- (2)設置分頻因子函數IWDG_SetPrescaler()
- (3)設置重裝載值函數IWDG_SetReload()
- (4)重裝載初值函數(喂狗)IWDG_ReloadCounter
- (5)啟動獨立看門狗函數IWDG_Enable()
- (6)獨立看門狗狀態獲取函數IWDG_GetFlagStatus()
- 七、例子(庫函數版)
一、獨立看門狗(IWDG)簡介
1、什么是看門狗
STM32 的獨立看門狗由內部專門的 40Khz 低速時鐘驅動,即使主時鐘發生故障,它也仍然有效。這里需要注意獨立看門狗的時鐘是一個內部 RC 時鐘,所以并不是準確的 40Khz,而是在 30~60Khz 之間的一個可變化的時鐘,只是我們在估算的時候,以 40Khz 的頻率來計算,看門狗對時間的要求不是很精確,所以,時鐘有些偏差,都是可以接受的。
首先我們得講解一下看門狗的原理。這個百度百科里面有很詳細的解釋。我們總結一下:單片機系統在外界的干擾下會出現程序跑飛的現象導致出現死循環,看門狗電路就是為了避免這種情況的發生。看門狗的作用就是在一定時間內(通過定時計數器實現)沒有接收喂狗信號(表示 MCU 已經掛了),便實現處理器的自動復位重啟(發送復位信號)。
總結:看門狗是為了避免程序跑飛而設置的,在程序正常運行情況下,會一直“喂狗”,使程序不會復位。可以這樣理解:在一個定時器中斷中,中斷服務函數里是整個程序的復位,在定時器之外,會一直給定時器重裝載初值(相當于喂狗),程序一直執行正常的話,定時器不會發生中斷,即不會進入中斷服務函數,不會執行復位程序;當程序跑飛時,由于沒有“喂狗”,定時器計數到0(如向下計數時),發生中斷,執行中斷服務函數里的復位程序,程序重新開始執行。
2、獨立看門狗應用場合
由于獨立看門狗時鐘源由LSI時鐘提供,并不精確,所以IWDG最適合應用于那些需要看門狗作為一個在主程序之外,能夠完全獨立工作,并且對時間精度要求較低的場合。
二、獨立看門狗時鐘
從時鐘框圖可以看到,看門狗的時鐘為內部低速時鐘40KHZ,我們知道LSI和HSI都是有內部RC振蕩電路生成的,輸出不穩定,所以這個時鐘大約為40KHZ,并不精準。
三、獨立看門狗的相關寄存器
(1)鍵寄存器(IWDG_KR)
該寄存器是低16位有效的32位寄存器。從上圖得到以下信息:
①IWDR_KR寄存器是只寫寄存器
②IWDR_KR寫入0XAAAA,才算“喂狗”,且一定時間間隔必須寫入,否則程序復位
③IWDR_KR寫入0X5555表示允許訪問IWDG_PR和IWDG_RLR寄存器,未寫入時這兩個寄存器處于保護狀態,無法進行寫操作
④IWDR_KR寫入0XCCCC,啟動看門狗
所以一般程序可以如下:
IWDG->KR=0x5555;//取消IWDG_PR和IWDG_RLR寄存器保護IWDG->PR= //設置這倆個寄存器IWDG->RLR=IWDG->KR=0xAAAA;//開始時給重裝載寄存器裝載初值IWDG->KR=0xCCCC;//啟動看門狗//程序中喂狗(程序其它地方)IWDG->KR=0xAAAA;//喂狗- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
(2)預分頻寄存器(IWDG_PR)
該寄存器是只有低3位有效的32位寄存器,之前的IWDG_KR寄存器中也強調過,要對IWDG_PR寄存器操作,必須先對IWDG_KR寫入0x5555。
我們知道,獨立看門狗的時鐘是40KHZ的LSI,經過本寄存器設置預分頻系數后,獨立看門狗的時鐘會變為40KHZ/預分頻因子。
(3)重裝載寄存器(IWDG_RLR)
該寄存器并不像SysTick定時器的重裝載寄存器一樣,該寄存器不需要手動裝載初值,只需設置好裝載值后,每次給IWDG_KR寄存器寫入0xAAAA,即可裝載初值。
(4)狀態寄存器(IWDG_SR)
該寄存器只有位0和位1有效,位0指示預分頻值更新、位1指示重裝載值更新;置1時表示正在更新,置0時表示更新完成。
通過該寄存器還可以獲取目前看門狗裝載值、預分頻器更新狀態:
while(IWDG->SR|0x00000002) {}//重裝載值更新中f(!(IWDG->SR|0x00000002)) {}//重裝載值更新完成- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
四、獨立看門狗編程順序
①取消寄存器寫保護(向 IWDG_KR 寫入 0X5555)
②設置獨立看門狗的預分頻系數和重裝載值(IWDG_PR和IWDG_PLR)
③重載計數值喂狗(向 IWDG_KR 寫入 0XAAAA)
④啟動看門狗(向 IWDG_KR 寫入 0XCCCC)
⑤程序的其他地方喂狗(向 IWDG_KR 寫入 0XAAAA)
五、例子(寄存器版)
例:按下KEY_UP后,喂狗,正常狀態下,LED0處于亮燈狀態。(當沒有喂狗時,程序被復位,此時LED0會滅了再被點亮)
LED和KEY的代碼之前總結過了,可以詳見:STM32F103五分鐘入門系列(五)按鍵實驗(庫函數+寄存器)
這里直接附代碼:
//led.h #ifndef LED_H #define LED_H void LED_Init(void);#endif- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
接下來寫獨立看門狗實驗,寄存器版比較簡單
首先看一下預分頻系數和重裝載值怎么搞。
LSI約為40KHZ,就當它是準確的40KHZ,預分頻系數為4、8、16…
如預分頻系數為16時,設置1s內喂狗。
則獨立看門狗時鐘為40kHZ/16,,每計數一次的時間:16/40ms,則1s需要計數:40000/16=2500;所以可以設置:
分頻系數為16,即IWDG_PR寄存器的值為010,即0x02
重裝載初值為2500,即IWDG_RLR寄存器的值為:2500
需要注意的是,重裝載值寄存器IWDG_RLR只有低12位有效,所以最大重裝載值為:2^12-1=4095
mian.c中代碼:
//main.c #include "stm32f10x.h" #include "led.h" #include "key.h" #include "sys.h" #include "delay.h"int main(void){ KEY_Init();LED_Init();delay_init();delay_ms(500);//為了看到程序復位PBout(5)=0;//點亮LED0IWDG->KR=0x5555;//取消IWDG_PR和IWDG_RLR寄存器保護IWDG->PR=0x02;IWDG->RLR=2500;//設置分頻系數和重裝載值//正常操作應該是先位與運算清空寄存器,再位或運算賦值IWDG->KR=0xAAAA;//初始狀態下,裝載初值IWDG->KR=0xCCCC;//啟動看門狗while(1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//檢測key_up按下{IWDG->KR=0xAAAA;//喂狗}}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
上述程序需要注意的是一定要延時一個時間,否則沒有喂狗導致程序重新執行,但是LED滅一下,根本看不出變化。
通過上述代碼,下載調試后發現:在KEY_UP未按下時,LED0每亮1s,滅0.5s,當長按KEY_UP時,LED0保持常亮狀態。
六、獨立看門狗常用庫函數
獨立看門狗的常用庫函數定義在stm32f10x_iwdg.h中:
(1)取消PR、RLR寄存器寫保護函數IWDG_WriteAccessCmd()
參數:
操作:
可以看到該函數就是將KR寫入0x5555,來取消PR、RLR寄存器寫保護
(2)設置分頻因子函數IWDG_SetPrescaler()
參數:
操作:
可以看到,該函數是將16進制數寫入PR寄存器,其分頻因子對應的16進制數:
(3)設置重裝載值函數IWDG_SetReload()
參數:
該參數由我們計算得來,由于RLR寄存器是低12位有效,所以該值<=0xFFF
操作:
直接將重裝載初值寫入到RLR寄存器
(4)重裝載初值函數(喂狗)IWDG_ReloadCounter
參數:
無
操作:
直接對KR寄存器寫入0xAAAA,喂狗。
(5)啟動獨立看門狗函數IWDG_Enable()
參數:
無
操作:
給KR寄存器寫入0xCCCC,啟動獨立看門狗。
(6)獨立看門狗狀態獲取函數IWDG_GetFlagStatus()
參數:
參數FLAG=0x0001|0x0002=0x0003
當獨立看門狗處于更新狀態時:(IWDG->SR & IWDG_FLAG) != (uint32_t)RESET,返回SET,表示正在更新,否則不在更新狀態。
操作:
直接獲取SR寄存器位0和位1的值
返回值:
返回SET(!0)表示處于更新中
返回RESET(0)表示不在更新中
七、例子(庫函數版)
庫函數版也比較簡單,直接把剛剛例子中寄存器部分替換為庫函數
代碼如下:
//mian.c #include "stm32f10x.h" #include "led.h" #include "key.h" #include "sys.h" #include "delay.h" int main(void){ KEY_Init();LED_Init();delay_init();delay_ms(500);//為了看到程序復位PBout(5)=0;//點亮LED0//IWDG->KR=0x5555;//取消IWDG_PR和IWDG_RLR寄存器保護IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//IWDG->PR=0x02;//設置重裝載值IWDG_SetPrescaler(IWDG_Prescaler_16);//IWDG->RLR=2500;//設置分頻系數和重裝載值IWDG_SetReload(2500);//設置分頻系數和重裝載值//正常操作應該是先位與運算清空寄存器,再位或運算賦值//IWDG->KR=0xAAAA;//初始狀態下,裝載初值IWDG_ReloadCounter();//IWDG->KR=0xCCCC;//啟動看門狗IWDG_Enable();while(1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//檢測key_up按下{//IWDG->KR=0xAAAA;//喂狗IWDG_ReloadCounter();}} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
總結
以上是生活随笔為你收集整理的STM32F103五分钟入门系列(十三)独立看门狗IWDG的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 启示录一
- 下一篇: 2021-04-23 - TS型网页视频