天天看點

《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗

第十八章獨立看門狗(IWDG)實驗​

本章我們學習如何使用STM32H7的獨立看門狗(以下簡稱IWDG)。STM32H7内部自帶了2個看門狗:獨立看門狗(IWDG)和視窗看門狗(WWDG)。這一章我們隻介紹獨立看門狗,視窗看門狗将在下一章介紹。在本章中,我們将通過按鍵KEY_UP來喂狗,然後通過LED0提示複位狀态。​

本章分為如下幾個小節:​

18.1 IWDG簡介​

18.2 硬體設計​

18.3 程式設計​

18.4 下載下傳驗證​

18.1 IWDG簡介​

獨立看門狗本質上是一個定時器,這個定時器有一個輸出端,可以輸出複位信号。該定時器是一個12位的遞減計數器,當計數器的值減到0的時候,就會産生一個複位信号。如果在計數沒減到0之前,重置計數器的值的話,那麼就不會産生複位信号,這個動作我們稱為喂狗。看門狗功能由VDD電壓域供電,在停止模式和待機模式下仍然可以工作。​

18.1.1 IWDG框圖​

下面先來學習IWDG框圖,通過學習IWDG框圖會有一個很好的整體掌握,同時對之後的程式設計也會有一個清晰的思路。​

《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗

圖18.1.1.1 IWDG框圖​

從IWDG框圖整體認知就是,IWDG有一個輸入(時鐘lsi_ck),經過一個8位的可程式設計預分頻器提供時鐘給一個12位遞減計數器,滿足條件就會輸出一個複位信号(iwdg1_out_rst)。IWDG内部輸入/輸出信号如下表:​

信号名稱​ 信号類型​ 說明​
lsi_ck​ 數字信号​ LSI時鐘​
iwdg1_out_rst​ 數字信号​ IWDG1 複位信号輸出​

表18.1.1.1 IWDG内部輸入/輸出信号​

STM32H750的獨立看門狗由内部專門的32Khz低速時鐘(lsi_ck)驅動,即使主時鐘發生故障,它也仍然有效。這裡需要注意獨立看門狗的時鐘是一個内部RC時鐘,是以并不是準确的32Khz,而是在17~47Khz之間的一個可變化的時鐘,隻是我們在估算的時候,以32Khz的頻率來計算,看門狗對時間的要求不是很精确,是以,時鐘有些偏差,都是可以接受的。​

18.1.2 IWDG寄存器​

IWDG的框圖很簡單,用到的寄存器也不多。我們主要用到其中3個寄存器:​

  • 鍵寄存器(IWDG_KR)​鍵寄存器可以看作是獨立看門狗的控制寄存器,其描述如圖18.1.2.1所示:​
  • 《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗
  • 圖18.1.2.1 WDG_KR寄存器​

    在鍵寄存器(IWDG_KR)中寫入0xCCCC,開始啟用獨立看門狗;此時計數器開始從其複位值0xFFF遞減計數。當計數器計數到末尾0x000時,會産生一個複位信号(IWDG_RESET)。 無論何時,隻要鍵寄存器IWDG_KR中被寫入0xAAAA, IWDG_RLR中的值就會被重新加載到計數器中進而避免産生看門狗複位 。​

    IWDG_PR和IWDG_RLR寄存器具有寫保護功能。要修改這兩個寄存器的值,必須先向IWDG_KR寄存器中寫入0x5555。将其他值寫入這個寄存器将會打亂操作順序,寄存器将重新被保護。重裝載操作(即寫入0xAAAA)也會啟動寫保護功能。 ​

  • 預分頻寄存器(IWDG_PR)​預分頻寄存器描述如圖18.1.2.2所示:​
  • 《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗
  • 圖18.1.2.2 IWDG_ PR寄存器​

    該寄存器用來設定看門狗時鐘(LSI)的分頻系數,最低為4分頻,最高位256分頻,該寄存器是一個32位的寄存器,但是我們隻用了最低3位,其他都是保留位。​

  • 重載寄存器(IWDG_ RLR)​
《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗

圖18.1.2.3 IWDG_ RLR寄存器​

該寄存器用來儲存重裝載到計數器中的值。該寄存器也是一個32位寄存器,隻有低12位是有效的。 ​

18.2 硬體設計​

1. 例程功能​

在配置看門狗後,LED0将常亮,如果KEY_UP按鍵按下,就喂狗,隻要KEY_UP不停的按,看門狗就一直不會産生複位,保持LED0的常亮,一旦超過看門狗定溢出時間(Tout)還沒按,那麼将會導緻程式重新開機,這将導緻LED0熄滅一次。​

2. 硬體資源​

1)RGB燈​

RED :LED0 - PB4​

2)獨立按鍵​

WK_UP - PA0。​

3)獨立看門狗​

3. 原理圖​

獨立看門狗實驗的核心是在STM32H750内部進行,并不需要外部電路。但是考慮到訓示目前狀态和喂狗等操作,我們需要2個IO口,一個用來輸入喂狗信号,另外一個用來訓示程式是否重新開機。喂狗我們采用闆上的KEY_UP鍵來操作,而程式重新開機,則是通過LED0來訓示的。​

18.3 程式設計​

18.3.1 IWDG的HAL庫驅動​

IWDG在HAL庫中的驅動代碼在stm32h7xx_hal_iwdg.c檔案(及其頭檔案)中。 ​

1. HAL_IWDG_Init函數​

IWDG的初始化函數,其聲明如下:​

HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);      
  • 函數描述:​用于初始化IWDG。​
  • 函數形參:​形參1是IWDG句柄,IWDG_HandleTypeDef結構體類型,其定義如下:​
typedef struct​
{​
 IWDG_TypeDef *Instance; /* IWDG寄存器基位址 */​
 IWDG_InitTypeDef Init; /* IWDG初始化參數 */​
}IWDG_HandleTypeDef;      
  • 1)Instance:指向IWDG寄存器基位址。2)Init:IWDG初始化結構體,用于配置計數器的相關參數。IWDG_InitTypeDef這個結構體類型定義如下:
typedef struct
{
 uint32_t Prescaler;  /* 預分頻系數 */
 uint32_t Reload;  /* 重裝載值 */
 uint32_t Window;  /* 視窗值 */      
  • } IWDG_InitTypeDef;

    1)Prescaler:預分頻系數,IWDG_PRESCALER_4到IWDG_PRESCALER_256。

    2)Reload:重裝載值,範圍:0到0x0FFF。

    3)Window:視窗值。

  • 函數傳回值:​HAL_StatusTypeDef枚舉類型的值。​2. HAL_IWDG_Refresh函數​HAL_IWDG_Refresh函數是獨立看門狗的喂狗函數。其聲明如下:​
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);      
  • 函數描述:​用于把重裝載寄存器的值重載到計數器中,喂狗,防止IWDG複位。​
  • 函數形參:​形參1是IWDG_HandleTypeDef結構體指針類型的IWDG句柄。​
  • 函數傳回值:​

HAL_StatusTypeDef枚舉類型的值。​

獨立看門狗配置步驟 ​

1)取消寄存器寫保護,設定看門狗預分頻系數和重裝載值​

首先我們必須取消IWDG_PR和IWDG_RLR寄存器的寫保護,這樣才可以設定寄存器IWDG_PR和IWDG_RLR的值。取消寫保護和設定預分頻系數以及重裝載值在HAL庫中是通過函數HAL_IWDG_Init實作的。​

通過該函數設定看門狗的分頻系數,和重裝載的值。看門狗的喂狗時間(也就是看門狗溢出時間)的計算方式為:​

Tout=((4×2^prer) ×rlr) /32      

其中Tout為看門狗溢出時間(機關為ms)。​

prer為看門狗時鐘預分頻值(IWDG_PR值),範圍為0~7。​

rlr為看門狗的重裝載值(IWDG_RLR的值)。​

比如我們設定prer值為4(4代表的是64分頻,HAL庫中可以使用宏定義辨別符IWDG_PRESCALER_64),rlr值為500,那麼就可以得到Tout=64×500/32=1000ms,這樣,看門狗的溢出時間就是1s,隻要你在一秒鐘之内,有一次寫入0XAAAA到IWDG_KR,就不會導緻看門狗複位(當然寫入多次也是可以的)。這裡需要提醒大家的是,看門狗的時鐘不是準确的32Khz,是以在喂狗的時候,最好不要太晚了,否則,有可能發生看門狗複位。​

2)重載計數值喂狗(向IWDG_KR寫入0XAAAA)​

在HAL中重載計數值的函數是HAL_IWDG_Refresh,該函數的作用是把值0xAAAA寫入到IWDG_KR寄存器,進而觸發計數器重載,即實作獨立看門狗的喂狗操作。​

3) 啟動看門狗(向IWDG_KR寫入0XCCCC)​

HAL庫函數裡面啟動獨立看門狗是通過宏定義辨別符來實作的:​

#define __HAL_IWDG_START(__HANDLE__) ​
 WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_ENABLE);      

我們隻需要調用宏定義辨別符__HAL_IWDG_START即可實作看門狗使能。實際上,當我們調用了看門狗初始化函數HAL_IWDG_Init之後,在内部已經調用了該宏啟動看門狗。​

18.3.2 程式流程圖​

《MiniPRO H750開發指南》第十八章 獨立看門狗(IWDG)實驗

圖18.3.2.1 獨立看門狗實驗程式流程圖​

18.3.3 程式解析​

1. IWDG驅動代碼​

這裡我們隻講解核心代碼,詳細的源碼請大家參考CD光牒本實驗對應源碼。獨立看門狗(IWDG)驅動源碼包括兩個檔案:wdg.c和wdg.h。​

wdg.h頭檔案隻有函數的聲明,就不解釋了。下面我們直接解析wdg.c的程式,先看IWDG的初始化函數,其定義如下:​

/**​
初始化獨立看門狗 ​
 * @param prer: IWDG_PRESCALER_4~IWDG_PRESCALER_256,對應4~256分頻​
分頻因子 = 4 * 2^prer. 但最大值隻能是256!​
自動重裝載值,0~0XFFF. ​
時間計算(大概):Tout=((4 * 2^prer) * rlr) / 32 (ms). ​
無​
 */​
void iwdg_init(uint8_t prer, uint16_t rlr)​
{​
 g_iwdg_handle.Instance = IWDG1;​
 g_iwdg_handle.Init.Prescaler = prer;  /* 設定IWDG分頻系數 */​
 g_iwdg_handle.Init.Reload = rlr;  /* 重裝載 */​
 g_iwdg_handle.Init.Window = IWDG_WINDOW_DISABLE;  /* 關閉視窗功能 */​
 HAL_IWDG_Init(&g_iwdg_handle); ​
}      

IWDG_Init是獨立看門狗初始化函數,主要設定預分頻數和重裝載寄存器的值。通過這兩個寄存器,就可以大概知道看門狗複位的時間周期為多少了。​

/**​
喂獨立看門狗​
無​
無​
 */​
void iwdg_feed(void)​
{ ​
 HAL_IWDG_Refresh(&g_iwdg_handle); /* 重裝載計數器 */​
}      

iwdg_feed函數用來喂狗,在該函數内部隻需調用HAL庫函數HAL_IWDG_Refresh。​

2. main.c代碼​

在main.c裡面編寫如下代碼:​

int main(void)​
{​
 sys_cache_enable();  /* 打開L1-Cache */​
 HAL_Init();  /* 初始化HAL庫 */​
 sys_stm32_clock_init(240, 2, 2, 4); /* 設定時鐘, 480Mhz */​
 delay_init(480);  /* 延時初始化 */​
 usart_init(115200);  /* 序列槽初始化為115200 */​
 led_init();  /* 初始化LED */​
 key_init();  /* 初始化按鍵 */​
 delay_ms(100);  /* 延時100ms再初始化看門狗,LED0的變化可見"*/​
 iwdg_init(IWDG_PRESCALER_64, 500); /* 預分頻數為64,重載值為500,溢出時間為1s */​
 LED0(0);  /* 點亮LED0(紅燈) */​
 while (1)​
 {​
 if (key_scan(0) == WKUP_PRES)  /* 如果WK_UP按下,則喂狗 */​
 {​
 iwdg_feed();  /* 喂狗 */​
 }​
 delay_ms(10);​
 }​
}      

18.4 下載下傳驗證​