目录
一、什么是看门狗?
二、独立看门狗IWDG
1.特点、本质及原理
2.配置
3.main.c代码
三、窗口看门狗WWDG
1.特点、本质及原理
2.配置
3.main.c代码
四、独立看门狗与窗口看门狗的比较
一、什么是看门狗?
看门狗主要是用来监测单片机运行状态和解决程序引起的故障的模块。
独立看门狗:
由于单片机的工作会受到外界的干扰,可能造成程序进入死循环或者程序跑飞,程序的正常运行被打断,单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态。为了防止进入这个情况便产生了一种专门用于实时监测单片机程序运行状态的模块或者芯片,俗称“看门狗”。
窗口看门狗:
用于监测单片机程序运行时效是否精准,主要检测软件异常。
二、独立看门狗IWDG
1.特点、本质及原理
1.特点:工作在主程序之外,能够完全独立工作,它的时钟是专用的低速时钟(LSI),由 VDD 电压供电, 在停止模式和待机模式下仍能工作,主要检测硬件的正常运行。
2.本质:1.是一个 12 位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即 IWDG_RESET ,CPU收到复位信号,系统复位重新运行。
2.在计数没减到0之前,重置了计数器的值的话,那么就不会产生复位信号,CPU收不到复位信号,系统就会正常运行不会复位,这个动作就是我们说的喂狗。
3.原理框图:
4.时钟:独立看门狗的时钟由独立的RC振荡器LSI提供,即使主时钟发生故障它依然可以运行。启用 IWDG后,LSI时钟会自动开启,无法停止可以重置。LSI经过一个8位的预分频器得到计数器时钟,LSI时钟频率并不精确,F1用40kHz。
5.预分频寄存器(IWDG_PR):
(1)分频系数算法:prer是IWDG_PR 的值。
6.重装载寄存器
重装载寄存器是一个12位的寄存器,用于存放重装载值,低12位有效,即最大值为4096,这个值的大小决定着独立看门狗的溢出时间。
7.键寄存器
是一个控制寄存器,主要有三种控制方式。由位15:0决定.
8.溢出时间计算公式
PSC是分频系数、RLR、是LSI时钟频率一般用40KHz。
2.配置
实现:溢出时间1s,按钮喂狗,串口查看状态
1.独立看门狗配置,设置溢出时间1s。PSC=64、RLR=625
2.按钮PA0 GPIO设置为输入input。
3.串口USART1打开,异步通讯(非中断)
4.时钟72KHz
3.main.c代码
/* USER CODE BEGIN Header *//********************************************************************************* @file : main.c* @brief: Main program body******************************************************************************* @attention** Copyright (c) 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 "usart.h"#include "gpio.h"/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include <string.h>//strlen所需头文件============================================/* 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 *//* 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();MX_USART1_UART_Init();/* USER CODE BEGIN 2 *///程序启动就让串口发送信息=========================================================HAL_UART_Transmit(&huart1,"程序启动...",strlen("程序启动..."),100);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *///检测按钮是否被按下==========================================================if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)HAL_IWDG_Refresh(&hiwdg);//重置看门狗计数HAL_Delay(50);//循环延时50ms/* USER CODE BEGIN 3 */}/* 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 */
三、窗口看门狗WWDG
1.特点、本质及原理
1.特点:用于监测单片机程序运行时效是否精准,主要检测软件异常,一般用于需要精准检测程序运行时间的场合。
2.本质:是一个能产生系统复位信号和提前唤醒中断的6位计数器。
(1)产生复位条件: 1.当递减计数器值从 0x40 减到 0x3F 时复位(即T6位跳变到0)
2.计数器的值大于 W[6:0] 值时喂狗会复位。
(2)产生中断条件: 1.当递减计数器等于 0x40 时可产生提前唤醒中断 (EWI)。
(3)要在窗口期内重装载计数器的值,才能防止复位,也就是所谓的喂狗。
3.原理
(1)窗口上限值:可以修改
(2)中断:可以设置是否中断
(3)提前唤醒:作用:可以在复位之前保存一些数据。
4.框图
(1)PCLK1最大36M
5.控制寄存器(WWDG_CR)
激活看门狗、计数器
6.配置寄存器(WWDG_CFR)
提前唤醒中断、预分频器、窗口值
7.状态寄存器(WWDG_SR)
提前唤醒中断标志
8.超时时间计算
参数:
(1)Tout是WWDG超时时间(没喂狗)
(2)Fwwdg是WWDG的时钟源频率(最大36M)
(3)4096是WWDG固定的预分频系数
(4)2^WDGTB是WWDG_CFR寄存器设置的预分频系数值
(5)T[5:0]是WWDG计数器低6位,最多63
2.配置
1.实现:程序启动时点 亮 LED1 ,300ms 后熄灭。在提前唤醒中断服务函数进行喂狗,同时翻转 LED2 状态。
2.值: T[6.0]七位计数器设置为127
W[6:0]七位窗口值设置 为95
2^WDGTB预分频系数设置 为8
3.时钟源频率Fwwdg 设置为36(来自RCC时钟控制器)
4.WWDG配置
5.LDE灯引脚设置PB8 输出 开始时高电平、PB9 输出 开始时高电平
3.main.c代码
/* USER CODE BEGIN Header *//********************************************************************************* @file : main.c* @brief: Main program body******************************************************************************* @attention** Copyright (c) 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 *///提前唤醒中断=============================================================void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg){HAL_WWDG_Refresh(hwwdg);//喂狗重置计数器HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//反转LDE灯} /* 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();//在狗启动之前点灯,程序启动亮300ms=============================================HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);HAL_Delay(300);MX_WWDG_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *///关灯===========================-==========================================HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);HAL_Delay(40);/* USER CODE BEGIN 3 */}/* 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 */