STM32H7窗口看门狗(WWDG)唤醒中断失效及配置问题咨询
STM32H7窗口看门狗(WWDG)问题排查与解决
问题描述
- 提前唤醒中断失效:配置了WWDG的EWI(提前唤醒中断),但系统复位前该中断从未触发,无法执行复位前的自定义代码。
- 窗口值配置异常:当窗口值设置为小于计数器初始值时,芯片无法正常工作,但手册明确说明窗口值可小于等于计数器值。
用户提供的代码
WWDG配置代码
hwwdg1.Instance = WWDG1; hwwdg1.Init.Prescaler = WWDG_PRESCALER_128; hwwdg1.Init.Window = 127; hwwdg1.Init.Counter = 127; hwwdg1.Init.EWIMode = WWDG_EWI_ENABLE; if (HAL_WWDG_Init(&hwwdg1) != HAL_OK) { Error_Handler(); }
主测试代码
int main(void) { MPU_Config(); HAL_Init(); SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_CRC_Init(); MX_RTC_Init(); MX_WWDG1_Init(); HAL_WWDG_Refresh(&hwwdg1); HAL_GPIO_WritePin(AlarmLEDsVDD_GPIO_Port, AlarmLEDsVDD_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(YellowLEDs_GPIO_Port, YellowLEDs_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(RedLEDs_GPIO_Port, RedLEDs_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(AlarmLEDsVDD_GPIO_Port, AlarmLEDsVDD_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(YellowLEDs_GPIO_Port, YellowLEDs_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(RedLEDs_GPIO_Port, RedLEDs_Pin, GPIO_PIN_RESET); int counter = 490; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_WWDG_Refresh(&hwwdg1); HAL_Delay(counter++); // limit is about 507-510 delay } /* USER CODE END 3 */ }
中断处理函数
void WWDG_IRQHandler(void) { /* USER CODE BEGIN WWDG_IRQn 0 */ /* USER CODE END WWDG_IRQn 0 */ HAL_WWDG_IRQHandler(&hwwdg1); /* USER CODE BEGIN WWDG_IRQn 1 */ /* USER CODE END WWDG_IRQn 1 */ }
问题分析与解决
问题1:提前唤醒中断未触发
核心原因及修复步骤
NVIC中断未配置使能
HAL库不会自动配置WWDG的NVIC中断,需要在HAL_WWDG_MspInit函数中手动添加NVIC配置,否则中断无法触发:void HAL_WWDG_MspInit(WWDG_HandleTypeDef* hwwdg) { if(hwwdg->Instance==WWDG1) { __HAL_RCC_WWDG1_CLK_ENABLE(); // 配置中断优先级,可根据实际需求调整 HAL_NVIC_SetPriority(WWDG_IRQn, 0, 0); HAL_NVIC_EnableIRQ(WWDG_IRQn); } }测试逻辑导致中断无触发机会
WWDG的提前唤醒中断仅在计数器递减到0x40(十进制64)时触发,随后计数器继续递减到0x3F时触发复位。
按用户配置计算WWDG总超时时间:假设PCLK1为100MHz,WWDG时钟为PCLK1/4=25MHz,预分频128,计数器从127递减到0x3F的总时间约为328ms。而用户初始延迟为490ms,远大于超时时间,导致计数器直接递减到复位值,根本没机会走到0x40触发中断。
修复测试逻辑:先保持小延迟保证正常刷新,再主动停止刷新等待中断触发:int counter = 100; while (1) { HAL_WWDG_Refresh(&hwwdg1); HAL_Delay(counter); if(counter >= 400) { // 停止刷新,等待中断触发后复位 while(1); } counter += 50; }未实现中断回调函数
HAL库中,HAL_WWDG_IRQHandler会调用HAL_WWDG_EarlyWakeupCallback执行自定义逻辑,用户需要重写该函数:void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) { // 复位前的处理代码,比如切换LED状态 HAL_GPIO_WritePin(YellowLEDs_GPIO_Port, YellowLEDs_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(RedLEDs_GPIO_Port, RedLEDs_Pin, GPIO_PIN_SET); // 代码要尽量精简,因为很快会触发复位 }
问题2:窗口值小于计数器值时芯片异常
核心原因及修复步骤
WWDG的窗口规则是:仅当当前计数器值大于窗口值时,才能执行刷新操作。如果在计数器值≤窗口值时调用HAL_WWDG_Refresh,会立即触发系统复位。
用户测试时主循环每次都调用刷新函数,当计数器递减到窗口值以下时,刷新操作直接触发复位,表现为“芯片无法正常工作”。
修复方法:
- 若不需要窗口限制,将窗口值设为最大值
0x7F(十进制127),此时刷新操作在计数器值0x7F~0x40范围内都允许。 - 若需要窗口限制,需在代码中判断计数器值是否大于窗口值,再执行刷新:
// 读取当前计数器值 uint32_t current_counter = WWDG1->CR & WWDG_CR_T; if(current_counter > hwwdg1.Init.Window) { HAL_WWDG_Refresh(&hwwdg1); }
内容的提问来源于stack exchange,提问作者ali .V
相关产品推荐
相关产品推荐

