本帖最后由 尹小舟 于 2024-8-9 20:46 编辑
STM32H5独立看门狗 介绍
独立看门狗(Independent Watchdog, IWDG)是微控制器(MCU)中一种重要的安全机制,用于监控系统的运行状态, 防止程序因意外情况(如死循环、程序跑飞等)而陷入无限执行状态, 从而无法响应外部事件或进行必要的系统重启。
IWDG 本质上是一个定时器,但其设计目的和功能与普通的定时器有所不同。
该定时器是一个 12 位的递减计数器,
计数器从预设的初始值开始递减,直到减到0。这个初始值通常可以配置,以决定看门狗的超时时间。
在计数器值减到0之前,通过软件或硬件的方式重置计数器的值,这个操作被称为“喂狗”。喂狗操作可以阻止复位信号的产生,并允许系统继续运行。
当计数器的值减到0时,如果此时没有通过“喂狗”操作重置计数器,则看门狗会输出一个复位信号,使系统复位。这是看门狗防止系统死锁的主要手段。或产生一个中断信号,进入看门狗中断。
看门狗功能由VDD电压域供电,即使在其他一些系统模块(如CPU)进入低功耗模式(如停止模式或待机模式)时,看门狗仍然可以正常工作,持续监控系统状态
使用场景:
- 防止软件死循环:如果程序因某种原因陷入死循环,看门狗可以在一定时间后复位系统,从而避免系统长时间无法响应。
- 硬件故障检测:在某些情况下,看门狗也可以用于检测硬件故障,如时钟源故障,导致系统无法正常运行。
- 系统监控:在需要高可靠性的系统中,看门狗可以作为系统健康状态的一个监控指标。
注意事项:
- 合理设置超时时间:超时时间设置过短可能导致系统频繁复位,影响正常操作;设置过长则可能无法及时响应系统异常。
- 确保喂狗操作:在系统正常运行时,必须确保在计数器减到0之前进行喂狗操作,以避免不必要的系统复位。
- 考虑低功耗影响:在低功耗模式下,需要特别注意看门狗的工作状态及其对系统功耗的影响。
IWDG框图
API介绍
IWDG 句柄
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; /* 窗口值 */
uint32_t EWI; /* IWDG 早期唤醒中是否唤醒以及比较器的值,设置为 0 表示关闭 EWI */
} IWDG_InitTypeDef;
1)Prescaler:预分频系数,IWDG_PRESCALER_4 到 IWDG_PRESCALER_256。
2)Reload:重装载值,范围:0 到 0x0FFF。
3)Window:窗口值。
4)EWI:比较器的值。
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
初始化独立看门狗,用于把重装载寄存器的值重载到计数器中,防止 IWDG 复位。
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
喂狗函数
程序代码
外部中断初始化
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
独立看门狗初始化
static void MX_IWDG_Init(void)
{
/* USER CODE END IWDG_Init 1 */
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_32;
hiwdg.Init.Window = IWDG_WINDOW_DISABLE;
hiwdg.Init.Reload = 500;
hiwdg.Init.EWI = 0;
if (HAL_IWDG_Init(&hiwdg) != HAL_OK)
{
Error_Handler();
}
}
main函数
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 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_ICACHE_Init();
MX_IWDG_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Initialize leds */
BSP_LED_Init(LED_GREEN);
/* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
/* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
{
Error_Handler();
}
/* USER CODE BEGIN BSP */
/* -- Sample board code to send message over COM1 port ---- */
printf("Welcome to STM32 world !\n");
/* Switch on leds */
BSP_LED_On(LED_GREEN);
led_gpio_init();
sw_gpio_init();
/* USER CODE END BSP */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* -- Sample board code for User push-button in interrupt mode ---- */
if (BspButtonState == BUTTON_PRESSED)
{
/* Update button state */
BspButtonState = BUTTON_RELEASED;
/* -- Sample board code to toggle leds ---- */
BSP_LED_Toggle(LED_GREEN);
if(HAL_IWDG_Refresh(&hiwdg) != HAL_OK)
{
/* Refresh Error */
Error_Handler();
}
/* ..... Perform your action ..... */
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
实验现象
不按按键触发中断的话就会复位打印
|