STM32F4 窗口看门狗(WWDG) 您所在的位置:网站首页 stm32看门狗怎么关闭 STM32F4 窗口看门狗(WWDG)

STM32F4 窗口看门狗(WWDG)

2024-05-17 19:12| 来源: 网络整理| 查看: 265

概述

  为了方便阅读,可以先阅读本人《STM32F407 独立看门狗 (IWDG)》

https://www.cnblogs.com/ding-ding-light/p/14472107.html

  与独立看门狗不同的是,窗口看门狗没有独立的时钟源,它是挂载在APB1下的一个片上外设,与独立看门狗类似,窗口看门狗也需要进行“喂狗”,只不过喂狗的时机被设置成计数器值需要在一个范围之内喂狗,不在这个范围之内喂狗或者低于这个范围的下限系统将发生复位,而这个范围便是上限值和下限值,其中下限值被设定死了是0x40,上限值由用户设置(最大为127)。

寄存器

  以上为窗口看门狗的功能框图,首先来自其中PCLK1时钟被WDG分频器分频后进入窗口看门狗;   寄存器WWDG_CR为看门狗计数器的值每隔一个时钟周期递减一次;   寄存器WWDG_CFR保存了预先设置好的上限值,当当前计数器的值T6:0>W6:0时,比较器输出为1,当这个时候进行写寄存器WWDG_CR,接下来的与门会输出1,在输入到或门也将输出1,便会触发复位,前提是寄存器WWDG_CR的WDGA位被置1表示允许窗口看门狗复位发生,这也对应了我之前所说的,当不在上限值和下限值这个范围之内喂狗便会触发复位;   上图中可以看出另外发生窗口看门狗复位的一种情况是T6为0时,也就是当前计数值已经小于0x40了,前提也是WWDG_CR的WDGA位被置1;   还有一个寄存器WWDG_CFR的EWI用于选择是否触发中断,当计数器值被减到正好0x40时,可以在中断函数中便可以选择设置一个喂狗的标志位,在主函数中进行喂狗,具体原因独立看门狗已经讲过了,不在赘述。还有一个WDGTB位时用于选择分频器。

窗口看门狗初始化

  通过上面的讲解,我相信初始化过程已经很明了了,有如下步骤:     1.打开WWDG的硬件时钟;     2.选择分频器;     3.设置窗口看门狗的上限值;     4.配置计数器的值;     5.NVIC配置;     6.使能窗口看门狗中断。

实验程序 #include "stm32f4xx.h" #include static GPIO_InitTypeDef GPIO_InitStructure; static NVIC_InitTypeDef NVIC_InitStructure; static USART_InitTypeDef USART_InitStructure; volatile uint8_t wwdg_event = 0; #pragma import(__use_no_semihosting_swi) struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int ch, FILE *f) { USART_SendData(USART1,ch); //等待数据发送成功 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } void _sys_exit(int return_code) { } void delay_us(uint32_t n) { SysTick->CTRL = 0; // Disable SysTick SysTick->LOAD = n*168-1; // 计数值 SysTick->VAL = 0; // Clear current value as well as count flag SysTick->CTRL = 5; // Enable SysTick timer with processor clock(168MHz) while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set SysTick->CTRL = 0; // Disable SysTick } void delay_ms(uint32_t n) { while(n--) { SysTick->CTRL = 0; // Disable SysTick SysTick->LOAD = 168000-1; // 计数值 Count from n to 0 (168000-1+1=168000 cycles) SysTick->VAL = 0; // Clear current value as well as count flag SysTick->CTRL = 5; // Enable SysTick timer with processor clock(168MHz) while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set SysTick->CTRL = 0; // Disable SysTick } } void usart1_init(uint32_t baud) { //使能端口A硬件时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能串口1硬件时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //配置PA9、PA10为复用功能引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA,&GPIO_InitStructure); //将PA9、PA10连接到USART1的硬件 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //配置USART1的相关参数:波特率、数据位、校验位 USART_InitStructure.USART_BaudRate = baud;//波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据位 USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//允许串口发送和接收数据 USART_Init(USART1, &USART_InitStructure); //使能串口1工作 USART_Cmd(USART1,ENABLE); } void usart1_send_str(char *str) { char *p = str; while(*p!='\0') { USART_SendData(USART1,*p); p++; //等待数据发送成功 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); } } void WWDG_NVICDisable(void) { NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&NVIC_InitStructure); } void WWDG_NVICEnable(void) { NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void wwdg_init(void) { //打开WWDG的硬件时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //配置预分频值 //窗口看门狗的硬件时钟频率=(42MHz/4096)/8=1281Hz //所以窗口看门狗的硬件时钟周期=1/1281 //到达时间窗口需要:1/1281*(127-80)=37毫秒 WWDG_SetPrescaler(WWDG_Prescaler_8); //窗口的上限值 WWDG_SetWindowValue(80); //配置它的计数值为127看,并使能窗口看门狗工作 WWDG_Enable(127); WWDG_NVICEnable(); //使能提前唤醒中断 WWDG_EnableIT(); } int main(void) { //串口1初始化波特率为115200bps usart1_init(115200); delay_ms(500); //发送数据 usart1_send_str("This is wwdg test\r\n"); //检测是否由窗口看门狗导致的复位 if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) { printf("wwdg reset cpu\r\n"); } //清空标志位 RCC_ClearFlag(); //窗口看门狗的初始化 wwdg_init(); while(1) { //延时40ms已经到达窗口时间 delay_ms(40); //该变量在中断函数中被改变,在这里需要使用到时,需要关闭中断,使该变量进行临界区 WWDG_NVICDisable(); if(1 == wwdg_event) { //刷新计数值(将计数值恢复为127) == 喂狗操作 WWDG_SetCounter(127); } WWDG_NVICEnable(); } } void WWDG_IRQHandler(void) { if(WWDG_GetFlagStatus()==SET) { wwdg_event = 1; //清空提前唤醒中断标志位 WWDG_ClearFlag(); } } 总结

  1.注意寄存器WWDG_CFR的中断位在置1后,此中断只有在复位后才由硬件清零,所以要关闭中断时只能在NVIC中关闭;   2.注意时间的计算;

相关下载 链接:https://pan.baidu.com/s/13qhRg5jOU4eqtZRiMOF9jg 提取码:czd2 复制这段内容后打开百度网盘手机App,操作更方便哦


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有