目录
前言
近期在做stm32低功耗项目的时候遇到了内部看门狗和低功耗模式(待机模式standy)冲突的问题,项目需求是mcu需要定时唤醒,时长可设,这个时候肯定想到的是rtc唤醒,因为在待机或者shutdown模式下只有rtc(好像还有低速计时器)可以实现计时功能,其它时钟均被关闭且上下文丢失,设置好休眠时间后发现,内部看门狗也会出发唤醒中断,然后重启mcu,而且在查阅了很多资料后发现,这个玩意儿只要初始化了就没办法关掉。好家伙,原来内部看门狗这么强大!
解决思路
1、内部看门狗只要初始化就没办法关闭,那如果在初始化之前进入休眠是不是就不会触发看门狗超时?
2、如果不能关闭,那为什么程序在debug调试窗口时,可以无限期的断点等待,而不会触发复位?是不是有其他方法可以关闭看门狗?
解决方案
1、在休眠之前执行一段中转代码,这部分代码负责写一个标志位,同时复位mcu,然后在系统初始化时(看门狗初始化前)读出该标志,由此判断是否需要进入休眠,这样的话程序在看门狗初始化之前进入休眠,看门狗不起作用,完美规避了看门狗复位的问题;如果不需要进入休眠,则正常进入app程序,正常初始化看门狗、喂狗。
#define SLEEP_FLAG_ADDR 0x00000000
//中转代码,放在需要执行休眠时
void sleep_tmp(void)
{
uint8_t flg = 1;
flash_write(SLEEP_FLAG_ADDR ,&flg,1);
nvic_sysreset(); //系统重启
}
//放在初始化,检测休眠标志位
void check_sleep_flag(void)
{
uint8_t flg = 0;
flash_read(SLEEP_FLAG_ADDR ,&flg,1);
if(flg)
{
flg = 0;
flash_write(SLEEP_FLAG_ADDR ,&flg,1); //清标志
entry_sleep(); //进入休眠
}
}
该方案需要有eeprom或者flash配合,相关实现伪代码如上图,可根据需要自行修改。
2、该方案也是查阅了很多资料后发现的,可以通过flash“选项字”寄存器冻结休眠模式(standy或者shutdown)下看门狗计数功能,在参考手册中也有相关提示(其实如果使用过dplink下载过程序的小伙伴应该发现过,flash选项字是可以配置的,其中就有这几项):
那么通过上边的描述,我们就可以关闭看门狗在休眠模式下的计数功能(不影响正常模式下看门狗工作),代码如下:
/* USER CODE BEGIN 0 */
void Config_Option_Bytes()
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct;
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
//没有配置过就配置一次,有必要判断一下是否配置过,因为每次配置完都会导致重启,不能每次上电都无条件配置一次
if ((OptionsBytesStruct.USERConfig & (FLASH_OPTR_IWDG_STANDY) != 0)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_USER;
OptionsBytesStruct.USERType = OB_USER_IWDG_STANDY;
OptionsBytesStruct.USERConfig &= (~FLASH_OPTR_IWDG_STANDY); //STANDY模式下停止看门狗计数
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
HAL_FLASH_OB_Unlock();
if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
//NVIC_SystemReset();
}
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
HAL_FLASH_OB_Launch(); //加载flash配置,修改过后会重启
}
}
/* USER CODE END 0 */
该函数放在系统初始化(可以放到看门狗初始化后边)第一次配置会重启,FLASH_OPTR寄存器的bit18使能后就不再重启了,上电观察发现看门狗在休眠模式下不起作用,完美!!!
作者有话
以上两种方案都已经实际验证且功能正常,小伙伴可以根据实际需求自行修改,如果有更好的处理方式,欢迎评论出来借鉴学习;如有不恰当的地方,也欢迎各位看官提出宝贵意见,拜拜