众所周知,看门狗的最大时间是非常有限的,但是低功耗应用会有较长时间的休眠时间(例如standby),往往还是无人值守的,这样为了防止程序跑飞,看门狗就成了必须。
然而看门狗一旦启动就没有办法停下来,在休眠时期也没有办法喂狗,请问这种情况如何处理?特别是针对STM32L051V8T6.
尝试standby模式下冻结看门狗定时器:
/**
* @brief 配置 IWDG 在 Standby 模式下冻结
* @NOTE 此函数会修改选项字节并触发系统复位
*/
void Configure_IWDG_FreezeInStandby(void)
{
// 1. 先检查当前配置是否需要修改
if ((FLASH->OPTR & FLASH_OPTR_IWDG_STDBY) == 0) {
return; // 已经是冻结模式
}
// 2. 解锁 Flash 和选项字节
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
// 3. 读取当前选项字节的原始值(低16位 = 数据,高16位 = 补码)
uint32_t ob_old = *(__IO uint32_t *)OB_BASE_ADDR;
uint32_t ob_new = ob_old;
// 4. 修改 IWDG_STDBY 位(bit22)为 0(冻结)
// 注意:只修改低16位的数据部分,高16位的补码需要同步更新
uint16_t data_old = (uint16_t)(ob_old & 0xFFFF);
uint16_t data_new = data_old & ~(1U << 22); // 清除 bit22
uint16_t complement = (uint16_t)(~data_new);
ob_new = ((uint32_t)complement << 16) | data_new;
// 5. 如果新旧值相同,则无需编程(理论上前面已判断过,这里再保护一次)
if (ob_old == ob_new) {
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
return;
}
// 6. 确保没有正在进行的操作
while ((FLASH->SR & FLASH_SR_BSY) != 0);
// 7. 擦除选项字节区域(一次擦除会影响所有选项字节,注意备份其它配置)
FLASH->PECR |= FLASH_PECR_ERASE; // 使能擦除
FLASH->PECR |= FLASH_PECR_PROG; // 使能编程
*(__IO uint32_t *)OB_BASE_ADDR = 0x00000000; // 启动擦除
while ((FLASH->SR & FLASH_SR_BSY) != 0);
FLASH->PECR &= ~FLASH_PECR_ERASE; // 关闭擦除
// 8. 写入新的选项字节值
*(__IO uint32_t *)OB_BASE_ADDR = ob_new;
while ((FLASH->SR & FLASH_SR_BSY) != 0);
// 9. 关闭编程,重新锁定
FLASH->PECR &= ~FLASH_PECR_PROG;
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
// 10. 触发选项字节加载并复位
HAL_FLASH_OB_Launch();
// 不会执行到这里
while (1);
}
看门狗这样初始化:
HAL_Init();
SystemClock_Config();
Configure_IWDG_FreezeInStandby();
MX_IWDG_Init();
MX_GPIO_Init();
在main函数这样调用:
HAL_Init();
SystemClock_Config();
Configure_IWDG_FreezeInStandby();
MX_IWDG_Init();
MX_GPIO_Init();
没有成功。请stm32l051v8t6看门狗iwdg在进入standby后可以冻结吗?如果能,如何才能冻结? |
哪位前辈可以帮我?
由于IWDG由LSI提供时钟源,可以在进入standby之前喂狗然后关闭LSI,就可以在standby模式下IWDG失效,退出standby模式后,再开启LSI时钟源然后喂狗。