日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F103五分钟入门系列(十三)独立看门狗IWDG

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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
//led.c #include "sys.h" #include "stm32f10x.h" #include "led.h" void LED_Init(void) {GPIO_InitTypeDef GPIO_InitStruct_B;GPIO_InitTypeDef GPIO_InitStruct_E;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE ,ENABLE);GPIO_InitStruct_B.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct_B.GPIO_Pin=GPIO_Pin_5;GPIO_InitStruct_B.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct_B);GPIO_InitStruct_E.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStruct_E.GPIO_Pin=GPIO_Pin_5;GPIO_InitStruct_E.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOE,&GPIO_InitStruct_E);GPIO_SetBits(GPIOB, GPIO_Pin_5);//PB5置高電平//GPIO_WriteBit(GPIOB, GPIO_Pin_5,1);//GPIO_Write(GPIOB,0x0020); //慎用//PBout(5)=1;GPIO_SetBits(GPIOE, GPIO_Pin_5);//PE5置高電平//GPIO_WriteBit(GPIOE, GPIO_Pin_5,1);//GPIO_Write(GPIOE,0x0020); //慎用//PEout(5)=1; }
  • 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
//key.h #ifndef KEY_H #define KEY_H void KEY_Init(void); #endif
  • 1
  • 2
  • 3
  • 4
  • 5
//key.c #include "stm32f10x.h" #include "sys.h" #include "key.h" void KEY_Init(void) {GPIO_InitTypeDef GPIO_InitStruct_A;GPIO_InitTypeDef GPIO_InitStruct_E;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE , ENABLE);//使能GPIOA和GPIOE(PA0 PE2、3、4)GPIO_InitStruct_A.GPIO_Mode=GPIO_Mode_IPD;GPIO_InitStruct_A.GPIO_Pin=GPIO_Pin_0 ;GPIO_InitStruct_A.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct_A);//PA0 key_up 下拉輸入GPIO_InitStruct_E.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct_E.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;GPIO_InitStruct_E.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOE, &GPIO_InitStruct_E);//PE2、3、4 key0、key1、key2 上拉輸入GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);GPIO_ResetBits(GPIOA, GPIO_Pin_0); }
  • 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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。