第3章營(yíng)銷型企業(yè)網(wǎng)站建設(shè)開魯seo網(wǎng)站
看門狗介紹
在由單片機(jī)構(gòu)成的微型計(jì)算機(jī)系統(tǒng)中,由于單片機(jī)的工作常常會(huì)受到來(lái)自外界電磁場(chǎng)的干擾,造成程序的跑飛,而陷入死循環(huán),程序的正常運(yùn)行被打斷,由單片機(jī)控制的系統(tǒng)無(wú)法繼續(xù)工作,會(huì)造成整個(gè)系統(tǒng)的陷入停滯狀態(tài),發(fā)生不可預(yù)料的后果,所以出于對(duì)單片機(jī)運(yùn)行狀態(tài)進(jìn)行實(shí)時(shí)監(jiān)測(cè)的考慮,便產(chǎn)生了一種專門用于監(jiān)測(cè)單片機(jī)程序運(yùn)行狀態(tài)的模塊或者芯片俗稱“看門狗“(watchdog)。
有一個(gè)程序員叫張三,老板養(yǎng)了一條狗用來(lái)監(jiān)督張三持續(xù)工作,張三需要定時(shí)喂養(yǎng)這條狗以確保老板知道自己一直在努力工作,如果有一次沒有喂養(yǎng)這條狗,那么狗就會(huì)反骨咬死張三,張三就會(huì)重新升天投胎為程序員繼續(xù)工作,同時(shí)老板還是派這條狗來(lái)監(jiān)督張三的工作,張三同樣也需要定時(shí)喂養(yǎng)他,往復(fù)持續(xù)。
獨(dú)立看門狗(IWDG)
獨(dú)立看門狗工作在主程序之外,能夠完全獨(dú)立工作,它的時(shí)鐘是專用的低速時(shí)鐘(LSI),由VDD電壓供電,在停止模式和待機(jī)模式下仍能工作。
獨(dú)立看門狗的本質(zhì)
獨(dú)立看門狗是一個(gè)12位的遞減計(jì)數(shù)器,當(dāng)計(jì)數(shù)器的值從某個(gè)值一直減到0的時(shí)候,系統(tǒng)就會(huì)產(chǎn)生-個(gè)復(fù)位信號(hào),即IWDG_RESET。
如果在計(jì)數(shù)沒減到0之前,刷新了計(jì)數(shù)器的值的話,那么就不會(huì)產(chǎn)生復(fù)位信號(hào),這個(gè)動(dòng)作就是我們經(jīng)常說(shuō)的喂狗。
獨(dú)立看門狗的時(shí)鐘
獨(dú)立看門狗的時(shí)鐘由獨(dú)立的RC振蕩器LSI提供,即使主時(shí)鐘發(fā)生故障它仍然有效,非常獨(dú)立。啟用IWDG后,LSI時(shí)鐘會(huì)自動(dòng)開啟。MCU內(nèi)部的RC頻率會(huì)在30kHz到60kHz之間變化,因此 LSI時(shí)鐘頻率并不精確,一般設(shè)定為40kHz。
LSI經(jīng)過(guò)一個(gè)8位的預(yù)分頻器得到計(jì)數(shù)器時(shí)鐘。
想要獲得獨(dú)立看門狗相對(duì)精準(zhǔn)的超時(shí)時(shí)間可以對(duì)LSI進(jìn)行校準(zhǔn)

獨(dú)立看門狗框圖

鍵寄存器(IWDG_KR)

獨(dú)立看門狗的控制寄存器,主要有三種控制方式。
預(yù)分頻寄存器(IWDG_PR)

分頻系數(shù)算法:PSC = 4 * 2^prer
prer是IWDG_PR的值,即當(dāng)IWDG_PR為010時(shí),即prer為2
重裝載寄存器(IWDG_RLR)

用于存放重裝載值,最大值為4096,該寄存器的值的大小決定了獨(dú)立看門狗的溢出時(shí)間
獨(dú)立看門狗的溢出時(shí)間與PSC和RLR的值有關(guān),溢出時(shí)間計(jì)算公式如下

獨(dú)立看門狗實(shí)驗(yàn)
開啟獨(dú)立看門狗,溢出時(shí)間為一秒,使用按鍵進(jìn)行喂狗,不喂狗時(shí)反復(fù)執(zhí)行main函數(shù),導(dǎo)致LED1閃爍,喂狗時(shí)只執(zhí)行一次main函數(shù),LED1常亮。
獨(dú)立看門狗喂狗函數(shù)HAL_IWDG_Refresh()
原型:HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
參數(shù):
IWDG_HandleTypeDef *hiwdg:獨(dú)立看門狗句柄
實(shí)例:HAL_IWDG_Refresh(&hiwdg);
使用STM32CubeMX創(chuàng)建工程
配置SYS

配置RCC

配置GPIO
PB9都配置為輸出高電平,PA0配置為下降沿觸發(fā)中斷

配置NVIC
將PA0的中斷的搶占優(yōu)先級(jí)配置為3,因?yàn)榇龝?huì)要在中斷處理函數(shù)中調(diào)用HAL_Delay(),而該函數(shù)要用到滴答定時(shí)器,而在程序初始化時(shí)默認(rèn)將滴答定時(shí)器的中斷優(yōu)先級(jí)設(shè)置為最低,因此其他中斷源很容易將其打斷。

配置IWDG

配置工程名稱、工程路徑

選擇固件庫(kù)

生成工程

main函數(shù)編寫
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "iwdg.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//按鍵PA0觸發(fā)的中斷if(GPIO_Pin == GPIO_PIN_0){HAL_Delay(50);if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){HAL_IWDG_Refresh(&hiwdg);//喂狗}}
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_IWDG_Init();/* USER CODE BEGIN 2 */HAL_NVIC_SetPriority(SysTick_IRQn,0,0); //把滴答定時(shí)器的搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)都設(shè)置為最高HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);HAL_Delay(500);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///如果沒喂狗的話,就不會(huì)執(zhí)行該循環(huán),即燈不會(huì)常亮HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.LSIState = RCC_LSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
窗口看門狗
窗口看門狗用于監(jiān)測(cè)單片機(jī)程序運(yùn)行時(shí)效是否精準(zhǔn),主要檢測(cè)軟件異常,一般用于需要精準(zhǔn)檢測(cè)程序運(yùn)行時(shí)間的場(chǎng)合。
窗口看門狗的本質(zhì)

是一個(gè)能產(chǎn)生系統(tǒng)復(fù)位信號(hào)和提前喚醒中斷的6位計(jì)數(shù)器。
產(chǎn)生復(fù)位條件:
當(dāng)遞減計(jì)數(shù)器值遞減減到0x3F時(shí)復(fù)位(即T6位跳變到0)
窗口值在0x3F~W[6:0](0x7F)之間,不在窗口值內(nèi)喂狗就會(huì)復(fù)位
產(chǎn)生中斷條件:
當(dāng)計(jì)數(shù)器遞減到0x40時(shí)可以產(chǎn)生提前喚醒中斷(EWI)。
在窗口期內(nèi)重裝載計(jì)數(shù)器的值,防止復(fù)位,也就是所謂的喂狗。
窗口看門狗的時(shí)鐘
窗口看門狗使用了RCC的時(shí)鐘PCLK1,最高為36MHz
窗口看門狗框圖

控制寄存器(WWDG_CR)

控制窗口關(guān)門狗是否開啟和配置窗口關(guān)門狗計(jì)數(shù)器初始值。
當(dāng)計(jì)數(shù)器值從40h變?yōu)?Fh時(shí)(T6變成0),產(chǎn)生看門狗復(fù)位。
配置寄存器(WWDG_CFR)

配置窗口關(guān)門狗的窗口上限值和配置預(yù)分頻器系數(shù)值
窗口看門狗的溢出時(shí)間

狀態(tài)寄存器(WWDG_SR)

配置窗口看門狗的提前喚醒中斷。
窗口看門狗實(shí)驗(yàn)
開啟窗門看門狗,計(jì)數(shù)器值設(shè)置為0x7F(127),窗口值設(shè)置為0x5F(95),預(yù)分頻器的時(shí)基為8,。不喂狗時(shí)反復(fù)執(zhí)行main函數(shù),導(dǎo)致LED1閃爍,喂狗時(shí)只執(zhí)行一次main函數(shù),LED1常亮。在提前喚醒中斷服務(wù)函數(shù)進(jìn)行喂狗,防止程序復(fù)位,LED1常亮,同時(shí)翻轉(zhuǎn)LED2的狀態(tài)。

窗口看門狗喂狗函數(shù)HAL_StatusTypeDef HAL_WWDG_Refresh()
原型:HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
參數(shù):
WWDG_HandleTypeDef *hwwdg:窗門看門狗句柄
實(shí)例:HAL_WWDG_Refresh(hwwdg);
使用STM32CubeMX創(chuàng)建工程
配置SYS

配置RCC


配置GPIO
PB9、PB8都配置為輸出高電平

配置NVIC

配置WWDG


配置工程名稱、工程路徑

選擇固件庫(kù)

生成工程

main函數(shù)編寫
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "wwdg.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *///窗口看門狗的提前喚醒中斷的中斷處理函數(shù)
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{HAL_WWDG_Refresh(hwwdg); //及時(shí)喂狗防止程序復(fù)位HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_WWDG_Init();/* USER CODE BEGIN 2 */HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);HAL_Delay(500);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);HAL_Delay(500);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///如果沒喂狗的話,就不會(huì)執(zhí)行該循環(huán),即LED1不會(huì)常亮HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while (1){}/* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
獨(dú)立看門狗和窗口看門狗的異同點(diǎn)
IWDG最適合應(yīng)用于那些需要看門狗作為一個(gè)在主程序之外,能夠完全獨(dú)立工作,并且對(duì)時(shí)間精度要求較低的場(chǎng)合。
WWDG最適合那些要求看門狗在精確計(jì)時(shí)窗口起作用的應(yīng)用程序。
對(duì)比點(diǎn) | 獨(dú)立看門狗 | 窗口看門狗 |
時(shí)鐘源 | 獨(dú)立時(shí)鐘,LSI(40KHz),不精確 | PCLK1或PCLK3,精確 |
復(fù)位條件 | 遞減計(jì)數(shù)到0 | 窗口期外喂狗或減到0x3F |
中斷 | 沒有中斷 | 計(jì)數(shù)值減到0x40可產(chǎn)生中斷 |
遞減計(jì)數(shù) 器位數(shù) | 12位(最大計(jì)數(shù)范圍:4096~0) | 7位(最大計(jì)數(shù)范圍:127~63) |
應(yīng)用場(chǎng)合 | 防止程序跑飛,死循環(huán),死機(jī) | 檢測(cè)程序時(shí)效,防止軟件異常 |