STM32 HAL库窗口看门狗
1.窗口看门狗基本原理
窗口看门狗与独立看门狗原理相同,都是计数器按照一定频率进行递减。递减到一定值而产生复位信号。不同的是独立看门狗需要减到0进行复位,而窗口看门狗递减到0x40(下窗口值)进行复位。
由二图WWDG_CR寄存器存放计数值(即为T[6:0]设置的递减计数器的值),由此设置的值将会按照时钟逐级递减到WWDG_CFG寄存器设置的值(即W[6:0]窗口看门狗的上窗口值),之后再逐一递减到0x3F产生复位信号。
2.独立看门狗与串口看门狗区别
①.窗口看门狗具有终端而独立看门狗没有中断。
②.窗口看门狗使用外部时钟,使用的是外部时钟,当外部时钟损坏将会影响其使用,独立看门狗使用内部时钟即使主频不工作了,看门狗也能正常工作。(由于独立时钟因此独立与系统之外)。
3.应用场合
独立看门狗主要用来监控硬件上的错误
窗口看门狗是系统内部故障探测器,如果系统时钟出现了错误,那么窗口看门狗也就失去了作用,主要用于监视软件的错误。
4.窗口看门狗的时钟
窗口看门狗来自PCLK1 时钟主频为42MHZ,由RCC控制器开启。数据手册规定,计数时钟为CK=PCLK1/4096(其中4096为手册给定的值,默认不可修改)。
分频系数由分频系数配置寄存器CFR的[8:7]进行配置,即WDGTB[1:0]配置,可以设置为[0,1,2,3]分别对应[1/2/4/8]分频,因此计数时钟频率为:CNT_CK=PCLK1/4096/(2^WDGTB)。
则通过上述公式计算计数一次的时间为:
上图以fPCLK1=30MHZ为例子,递减计数器总共有7位T[6:0]假设为0x7F当第6位变为0的时候即变为0x3F,可知T[5:0]为实际计数值。因此当T[5:0]变为0时,即T[6:0]此时为0x40,当再递减一次就会产生复位信号,那么那这减一的时间就等于计数器的周期 =1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB) = 1/36 * 4096*2^0 = 136.53us
其他以此类推。
5.窗口看门狗寄存器:
①.看门狗控制寄存器(WWDG_CR)
①.WDGA此位将在看门狗到达0x3F进行复位时由软件的置位,从而产生复位信号。
②.T[6:0]该部分存放窗口看门狗的计数值,当全部设置为1的时候为计数器的最大值即0x7F当到达窗口下限的时候0X40即T[5:0]全为0,而T6位为1,从而得知计数器的计数范围所用的即为T[5:0为]位。当再递减一个数将会发送复位信号。
2.配置寄存器(WWDG_CFR)
①.可使用EWI位设置提前唤醒功能,置1时使能该功能,一旦使能该功能,当计数器递减到下窗口值(0x40)的时候将会进入中断,此时说明程序必有问题,可在中断 当中进行保存重要的数据。
②.WDGTB即上述内容中设置分频值内容,共2位[1:0]可设置为0/1/2/3,对应1/2/4/8分频。
③.W[6:0]用于设置上窗口值,在计数器T[6:0]设置的值到W[6:0]范围内不允许喂狗刷新,否则将会产生复位,在W[6:0]到0x40(下窗口值)可进行喂狗。
3.状态寄存器(WWDG_SR)
该寄存器将由硬件置位,软件置位无效,置位后代表提前唤醒终端标志。
未使能终端无效。可进行读取寄存器判断状态。
6.Cubemx配置(以STM32F103ZET6为例)
①.代码配置
②.相关接口说明
HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg);//窗口看门狗软件初始化
HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg);//窗口看门狗硬件(MCU)初始化
HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);//窗口看门狗喂狗
HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg);//窗口看门狗中断服务函数
HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg);//窗口看门狗回调函数,弱定义函数可自定义开发
③.代码段展示
以下代码利用窗口看门狗提前进入中断特性,在最后0x40时进行LED反转和喂狗操作。(灯闪烁的时间间隔取决于设置的递减计数值到-0x40时间)
例如下列程序:
0x7f: 为递减计数值到0x40共计数64个数
cubemx配置PCLK1时钟设置为4.5MHZ,分频为1
则f=fpclk1/4096/prc=4.5Mhz/4096/1=1098.63hz
t=1/f= 9.1010^-4s
T=CNTt=64* 9.1010^-4=0.058s=58ms切换一次
58ms2=116ms将亮一次(2为亮灭状态切换)
void MX_WWDG_Init(void)
{
/* USER CODE BEGIN WWDG_Init 0 */
/* USER CODE END WWDG_Init 0 */
/* USER CODE BEGIN WWDG_Init 1 */
/* USER CODE END WWDG_Init 1 */
hwwdg.Instance = WWDG; //句柄
hwwdg.Init.Prescaler = WWDG_PRESCALER_1;//1分频(不分频)
hwwdg.Init.Window = 0x4f; //上窗口值
hwwdg.Init.Counter = 0x7f; //计数值
hwwdg.Init.EWIMode = WWDG_EWI_ENABLE; //提前中断使能(计数器递减到0x40时将提前进入中断做复位前重要数据保存等处理)
if (HAL_WWDG_Init(&hwwdg) != HAL_OK) //初始化使能进入该函数将会调用 HAL_WWDG_MspInit
{
Error_Handler();
}
/* USER CODE BEGIN WWDG_Init 2 */
/* USER CODE END WWDG_Init 2 */
}
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_WWDG_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);//当看门狗递减到0x40时将会反转该LED
HAL_WWDG_Refresh(hwwdg);//复位前喂狗
}