stm32電子時鐘設計(正點原子STM32Mini板資料連載)
2023-05-23 14:44:26
1)實驗平臺:正點原子STM32mini開發板2)摘自《正點原子STM32 不完全手冊(HAL 庫版)》關注官方微信號公眾號,獲取更多資料:正點原子
第十章 獨立看門狗(IWDG)實驗
這一章,我們將向大家介紹如何使用 STM32 的獨立看門狗(以下簡稱 IWDG)。STM32 內
部自帶了 2 個看門狗:獨立看門狗(IWDG)和窗口看門狗(WWDG)。這一章我們只介紹獨
立看門狗,窗口看門狗將在下一章介紹。在本章中,我們將通過按鍵 WK_UP 來餵狗,然後通
過 DS0 提示復位狀態。本章分為如下幾個部分:
10.1 STM32 獨立看門狗簡介
10.2 硬體設計
10.3 軟體設計
10.4 下載驗證
10.1 STM32 獨立看門狗簡介
STM32 的獨立看門狗由內部專門的 40Khz 低速時鐘驅動,即使主時鐘發生故障,它也仍然
有效。這裡需要注意獨立看門狗的時鐘是一個內部 RC 時鐘,所以並不是準確的 40Khz,而是
在 30~60Khz 之間的一個可變化的時鐘,只是我們在估算的時候,以 40Khz 的頻率來計算,看
門狗對時間的要求不是很精確,所以,時鐘有些偏差,都是可以接受的。
獨立看門狗有幾個寄存器與我們這節相關,我們分別介紹這幾個寄存器,首先是鍵值寄存
器 IWDG_KR,該寄存器的各位描述如圖 10.1.1 所示:
圖 10.1.1 IWDG_KR 寄存器各位描述
在鍵寄存器(IWDG_KR)中寫入 0xCCCC,開始啟用獨立看門狗;此時計數器開始從其復位
值 0xFFF 遞減計數。當計數器計數到末尾 0x000 時,會產生一個復位信號(IWDG_RESET)。 無
論何時,只要鍵寄存器 IWDG_KR 中被寫入 0xAAAA, IWDG_RLR 中的值就會被重新加載到
計數器中從而避免產生看門狗復位 。
IWDG_PR 和 IWDG_RLR 寄存器具有防寫功能。要修改這兩個寄存器的值,必須先向
IWDG_KR 寄存器中寫入 0x5555。將其他值寫入這個寄存器將會打亂操作順序,寄存器將重新
被保護。重裝載操作(即寫入 0xAAAA)也會啟動防寫功能。
接下來,我們介紹預分頻寄存器(IWDG_PR),該寄存器用來設置看門狗時鐘的分頻係數,
最低為 4,最高位 256,該寄存器是一個 32 位的寄存器,但是我們只用了最低 3 位,其他都是
保留位。預分頻寄存器各位定義如圖 10.1.2 所示:
圖 10.1.2 IWDG_ PR 寄存器各位描述
在介紹完 IWDG_PR 之後,我們介紹一下重裝載寄存器。該寄存器用來保存重裝載到計數
器中的值。該寄存器也是一個 32 位寄存器,但是只有低 12 位是有效的,該寄存器的各位描述
如圖 10.1.3 所示:
圖 10.1.3 重裝載寄存器各位描述
只要對以上三個寄存器進行相應的設置,我們就可以啟動 STM32F1 的獨立看門狗。獨立
看 門 狗 相 關 的 庫 函 數 操 作 函 數 在 文 件 stm32f1xx_hal_iwdg.c 和 對 應 的 頭 文 件
stm32f1xx_hal_iwdg.h 中。
接下來我們講解一下通過庫函數來配置獨立看門狗的步驟:
1)取消寄存器防寫(向 IWDG_KR 寫入 0X5555)
首先我們必須取消 IWDG_PR 和 IWDG_RLR 寄存器的防寫,這樣才可以設置寄存器
IWDG_PR 和 IWDG_RLR 的值。取消防寫和設置預分頻係數以及重裝載值在 HAL 庫中是通
過函數 HAL_IWDG_Init 實現的。該函數聲明為:
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);
該函數只有一個入口參數 hiwdg,該參數是 IWDG_HandleTypeDef 結構體指針類型。接下
來我們看看結構體 IWDG_HandleTypeDef 定義:
typedef struct
{
IWDG_TypeDef *Instance;
IWDG_InitTypeDef Init;
}IWDG_HandleTypeDef;
成員變量 Instance 用來設置看門狗寄存器基地址,實際上在 HAL 庫中已經通過標識符定義
了,這裡對於獨立看門狗直接設置為標識符 IWDG 即可。
成員變量 Init 是一個 IWDG_InitTypeDef 結構體類型,該結構體只有 2 個成員變量,分別用
來設置獨立看門狗的預分頻係數和重裝載值,定義如下:
typedef struct
{
uint32_t Prescaler;
uint32_t Reload;
}IWDG_InitTypeDef;
成員變量 Lock 是一個鎖存變量,該變量在 HAL 庫中當操作配置 IWDG 之前設置為鎖住
LOCK,當配置操作完成之後設置為 UNLOCK,實際上是一個操作狀態標識符。
成員變量 State 也是 HAL 定義的一個過程標識符,用來記錄 IWDG 處理狀態。
HAL_IWDG_Init 函數使用的一般方法為:
IWDG_HandleTypeDef IWDG_Handler; //獨立看門狗句柄
IWDG_Handler.Instance=IWDG;
//獨立看門狗
IWDG_Handler.Init.Prescaler=IWDG_PRESCALER_64; //設置 IWDG 分頻係數
IWDG_Handler.Init.Reload=500; //重裝載值
HAL_IWDG_Init(&IWDG_Handler);
上面程序的作用是初始化 IWDG,設置分頻係數為 64,重裝載值為 500。設置完預分頻系
數和重裝載值後,我們就可以知道看門狗的餵狗時間(也就是看門狗溢出時間),該時間的計算
方式為:
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,該函數聲明為:
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);
該函數有一個入口參數為前面講解的 IWDG_HandleTypeDef 結構體類型指針,它的作用是
把值0xAAAA寫入到IWDG_KR寄存器,從而觸發計數器重載,即實現獨立看門狗的餵狗操作。
3) 啟動看門狗(向 IWDG_KR 寫入 0XCCCC)
HAL 庫函數裡面啟動獨立看門狗的函數是__HAL_IWDG_START:
__HAL_IWDG_START(hiwdg);
通過上面 3 個步驟,我們就可以啟動 STM32F1 的獨立看門狗了,使能了看門狗,在程序
裡面就必須間隔一定時間餵狗,否則將導致程序復位。利用這一點,我們本章將通過一個 LED
燈來指示程序是否重啟,來驗證 STM32F1 的獨立看門狗。
在配置看門狗後,DS0 將常亮,如果 KEY_UP 按鍵按下,就餵狗,只要 KEY_UP 不停的
按,看門狗就一直不會產生復位,保持 DS0 的常亮,一旦超過看門狗定溢出時間(Tout)還沒
按,那麼將會導致程序重啟,這將導致 DS0 熄滅一次。
10.2 硬體設計
本實驗用到的硬體資源有:
1) 指示燈 DS0
2) WK_UP 按鍵
3) 獨立看門狗
前面兩個在之前都有介紹,而獨立看門狗實驗的核心是在 STM32 內部進行,並不需要外
部電路。但是考慮到指示當前狀態和餵狗等操作,我們需要 2 個 IO 口,一個用來輸入餵狗信
號,另外一個用來指示程序是否重啟。餵狗我們採用板上的 WK_UP 鍵來操作,而程序重啟,則是通過 DS0 來指示的。
10.3 軟體設計
軟體設計我們依舊是在上一章代碼的基礎上修改,因為沒用到外部中斷,所以先去掉 exti.c
(注意,此時 HARDWARE 組僅剩:led.c 和 key.c),然後在 HARDWARE 文件夾下面新建一個
WDG 的文件夾,用來保存與看門狗相關的代碼。再打開工程,新建 wdg.c 和 wdg.h 兩個文件,
並保存在 WDG 文件夾下,並將 WDG 文件夾加入頭文件包含路徑。
在 wdg.c 裡面輸入如下代碼:
#include "wdg.h"
IWDG_HandleTypeDef IWDG_Handler; //獨立看門狗句柄
//初始化獨立看門狗
//prer:分頻數:IWDG_PRESCALER_4~IWDG_PRESCALER_256
//rlr:自動重裝載值,0~0XFFF.
//時間計算(大概):Tout=((4*2^prer)*rlr)/32 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_Handler.Instance=IWDG;
IWDG_Handler.Init.Prescaler=prer;
//設置 IWDG 分頻係數
IWDG_Handler.Init.Reload=rlr;
//重裝載值
HAL_IWDG_Init(&IWDG_Handler);
//初始化 IWDG,默認會開啟獨立看門狗
}
//餵獨立看門狗
void IWDG_Feed(void)
{
HAL_IWDG_Refresh(&IWDG_Handler); //餵狗
}
該代碼就 2 個函數,void IWDG_Init(u8 prer,u16 rlr)是獨立看門狗初始化函數,就是按照
上面介紹的步驟來初始化獨立看門狗的。該函數有 2 個參數,分別用來設置與預分頻數與重裝
寄存器的值的。通過這兩個參數,就可以大概知道看門狗復位的時間周期為多少了。其計算方
式上面有詳細的介紹,這裡不再多說了。
void IWDG_Feed(void)函數,該函數用來餵狗,因為 STM32 的餵狗只需要向關鍵字寄存器
寫入 0XAAAA 即可,也就是調用庫函數 HAL_IWDG_Refresh,所以這個函數也是很簡單的。
iwdg.h 內容比較簡單,主要是一些函數申明,這裡我們忽略不講解。
接下來我們看看主函數,主程序裡面我們先初始化一下系統代碼,然後啟動按鍵輸入和看
門狗,在看門狗開啟後馬上點亮 LED0(DS0),並進入死循環等待按鍵的輸入,一旦 KEY_UP
有按鍵,則餵狗,否則等待 IWDG 復位的到來。該部分代碼如下:
int main(void)
{
HAL_Init; //初始化 HAL 庫
Stm32_Clock_Init(RCC_PLL_MUL9); //設置時鐘,72M
delay_init(72);
//初始化延時函數
uart_init(115200);
//初始化串口
LED_Init;
//初始化 LED
KEY_Init;
//初始化按鍵
delay_ms(100); //延時 100ms 再初始化看門狗,LED0 的變化"可見"
IWDG_Init(IWDG_PRESCALER_64,500);//分頻數為 64,重載值為 500,溢出時間為 1s
LED0=0;
while(1)
{
if(KEY_Scan(0)==WKUP_PRES) //如果 WK_UP 按下,餵狗
{
IWDG_Feed;
//餵狗
}
delay_ms(10);
}
}
上面的代碼,鑑於篇幅考慮,我們沒有把頭文件給列出來(後續實例將會採用類同的方式
處理),因為以後我們包含的頭文件會越來越多,大家想看,可以直接打開光碟相關源碼查看。
至此,獨立看門狗的實驗代碼,我們就全部編寫完了,接著要做的就是下載驗證了,看看我們
的代碼是否真的正確。
10.4 下載驗證
在編譯成功之後,我們就可以下載代碼到 MiniSTM32 開發板上,實際驗證一下,我們的程
序是否正確。下載代碼後,可以看到 DS0 不停的閃爍,證明程序在不停的復位,否則只會 DS0
常亮。這時我們試試不停的按 WK_UP 按鍵,可以看到 DS0 就常亮了,不會再閃爍。說明我們
的實驗是成功的
,