文章目录
- 一、基础知识点
- 二、开发环境
- 三、STM32CubeMX相关配置
- 四、Vscode代码讲解
- 五、结果演示
一、基础知识点
独立看门狗和窗口看门狗的区别:
独立看门狗在系统在待机、停机、睡眠阶段还会起效果,这就会导致在做低功耗的时候,看门狗还是会运作复位。
窗口看门狗时钟来源于系统时钟,因此系统在待机、停机、睡眠阶段窗口看门狗会随之停止工作。
WWDG主要特性
1、可编程的自由运行递减计数器
2、条件复位
─ 当递减计数器的值小于0x40, (若看门狗被启动)则产生复位。
─ 当递减计数器在窗口外被重新装载, (若看门狗被启动)则产生复位。
3、如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以被用于重装载计数器以避免WWDG复位。
WWDG内部框图
看门狗计数器共7位,WDGA是使能位。
WWDG_CFR为配置寄存器也有7位值和WWDG_CR进行比较输出。
时钟来源于系统时钟,因此系统在待机、停机、睡眠阶段窗口看门狗会停止工作。
WDGTB看门狗预分频器对系统时钟进行分频处理。
窗口看门狗时序图
横轴为时间,纵轴为计数值(也就是WWDG_CR寄存器)。
计数值有两个数值:
3Fh: 计数值小于0x40, (若看门狗被启动)则产生复位。
W[6:0]: 窗口值(也就是WWDG_CFR),值范围0xc0~0xff
由这两个值构成的一段时间就是看门狗的刷新窗口。
计数值刷新必须在看门狗刷新窗口中刷新,如果计数值小于3Fh或者大于W[6:0]区域刷新都会产生系统复位。
看门狗公式中T[5:0]+1是为什么?计数值不应该是T[6:0]吗?
这是由于计数值最低到0x40,也就是说低于0x40就复位,则T[6:0]-0x40 = T[5:0]+1
二、开发环境
1、硬件开发准备
主控:STM32F103ZET6
芯片内部窗口看门狗模块WWDG
2、软件开发准备
软件开发使用虚拟机 + VScode + STM32Cube 开发STM32,在虚拟机中直接完成编译下载。
该部分可参考:软件开发环境构建
三、STM32CubeMX相关配置
1、STM32CubeMX基本配置
本实验基于CubeMX详解构建基本框架 进行开发。
2、窗口看门狗相关配置
3、窗口看门狗中断优先级配置(配置最高)
四、Vscode代码讲解
1、定义窗口看门狗相关结构体并初始化
typedef struct MyWWDG_s
{
uint32_t WWDG_flag;
void (*Feed_WDG)(void);
} MyWWDG_t;
extern MyWWDG_t MyWWDG;
MyWWDG_t MyWWDG =
{
TRUE,
Feed_WDG
};
2、窗口看门狗喂狗具体函数实现
static void Feed_WDG(void)
{
HAL_WWDG_Refresh(&hwwdg);
}
3、重构窗口看门狗中断回调函数
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
if(MyWWDG.WWDG_flag == TRUE)
{
MyWWDG.Feed_WDG(); // 喂狗
}
}
窗口看门狗中断处理函数解析:
void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)
{
/* 检测窗口看门狗中断是否使能 */
if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)
{
/* 检测窗口看门狗中断标志位,是否看门狗中断产生 */
if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)
{
/* 清除看门狗标志位 */
__HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);
/* 调用看门狗中断回调函数,这是个弱函数允许用户重构 */
HAL_WWDG_EarlyWakeupCallback(hwwdg);
}
}
}
测试看门狗部分,通过之前触摸按键控制喂狗动作(改变看门狗标志位WWDG_flag)
static void Key3_Monitoring_Function(void)
{
if(Key3.key_flag == TRUE)
{
Key3.key_press = FALSE;
Key3.key_hold = TRUE;
for(int i=0; i<200; i++)
{
HAL_Delay(10);
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin))
{
Key3.key_press = TRUE;
Key3.key_hold = FALSE;
break;
}
}
}
if( Key3.key_press == TRUE )
{
#ifdef STM32_F407_WWDG
MyWWDG.WWDG_flag = FALSE;
printf(" System restart \n\r ");
#endif
LED3_Toggle;
}
if( Key3.key_hold == TRUE )
{
LED3_ON;
HAL_Delay(500);
LED3_OFF;
}
Key3.key_flag = FALSE;
Key3.key_press = FALSE;
Key3.key_hold = FALSE;
}