1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html#
第十五章 窗口看门狗实验
本章介绍APM32F407窗口看门狗(WWDT)的使用,窗口看门狗与独立看门狗一样能够帮助CPU在进入错误状态或程序跑飞时进行复位,不过窗口看门狗相对于独立看门狗限制了“喂狗”的最小间隔,若两次“喂狗”的间隔太短,一样会产生复位。通过本章的学习,读者将学习到WWDT的使用。
本章分为如下几个小节:
15.1 硬件设计
15.2 程序设计
15.3 下载验证
15.1 硬件设计
15.1.1 例程功能
- 程序运行后,点亮LED0等待300毫秒后开启窗口看门狗,后进入死循环等待窗口看门狗的中断在窗口看门狗的中断服务函数中执行喂狗和翻转LED1状态的操作,能观察到的现象为LED0在程序启动时闪烁一下,随后LED1不停闪烁
15.1.2 硬件资源 - LED
LED0 - PF9
LED1 - PF10 - 窗口看门狗
15.1.3 原理图
本章实验使用的窗口看门狗为APM32F407的片上资源,因此并没有相应的连接原理图。
15.2 程序设计
15.2.1 Geehy标准库的WWDT驱动
本章实验使用到了WWDT的提前唤醒中断,提前唤醒中断指的是WWDT在“喂狗”超时即将进行复位前由WWDT产生的中断,本章实验就在WWDT的提前唤醒中断服务函数中进行“喂狗”。在使用WWDT前,需要先对其进行初始化,在初始化中,需要使能WWDT并配置WWDT的预分频系数和窗口值,还要进行使能WWDT中断的相关操作,具体的步骤如下:
①:使能WWDT
②:配置WWDT预分频系数
③:配置WWDT窗口值
④:使能WWDT的提前唤醒中断
⑤:使能WWDT中断,并配置其相关的中断优先级
⑥:在WWDT提前唤醒中对其进行“喂狗”
在Geehy标准库中对应的驱动函数如下:
①:使能WWDT
该函数用于使能WWDT,其函数原型如下所示:
void WWDT_Enable(uint8_t counter);
该函数的形参描述,如下表所示:
表15.2.1.1 函数WWDT_Enable()形参描述
该函数的返回值描述,如下表所示:
表15.2.1.2 函数WWDT_Enable()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_wwdt.h"
void example_fun(void)
{
/* 使能WWDT */
WWDT_Enable(0x7F);
}
②:配置WWDT预分频系数
该函数用于配置WWDT的预分频系数,预分频系数决定了WWDT计数的快慢,其函数原型如下所示:
void WWDT_ConfigTimebase(WWDT_TIME_BASE_T timeBase);
该函数的形参描述,如下表所示:
表15.2.1.3 函数WWDT_ConfigTimebase()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表15.2.1.4 函数WWDT_ConfigTimebase()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_wwdt.h"
void example_fun(void)
{
/* 配置WWDT的预分频系数
* WWDT的计数时钟为(PCLK1/4096)/8
*/
WWDT_ConfigTimebase(WWDT_TIME_BASE_8);
}
③:配置WWDT窗口值
该函数用于配置WWDT的窗口值,在WWDT的计数值减少到窗口值之前进行“喂狗”,将为导致WWDT复位,其函数原型如下所示:
void WWDT_ConfigWindowData(uint8_t windowData);
该函数的形参描述,如下表所示:
形参 描述
windowData WWDT的窗口值
表15.2.1.5 函数WWDT_ConfigWindowData()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表15.2.1.6 函数WWDT_ConfigWindowData()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_wwdt.h"
void example_fun(void)
{
/* 配置WWDT窗口值 */
WWDT_ConfigWindowData(0x5F);
}
④:使能WWDT提前唤醒中断
该函数用于使能WWDT的提前唤醒中断,其函数原型如下所示:
void WWDT_EnableEWI(void);
该函数的形参描述,如下表所示:
形参 描述
无 无
表15.2.1.7 函数WWDT_EnableEWI()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表15.2.1.8 函数WWDT_EnableEWI()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_wwdt.h"
void example_fun(void)
{
/* 使能WWDT提前唤醒中断 */
WWDT_EnableEWI();
}
⑤:配置WWDT中断
请见第12.2.3小节中配置中断的相关内容。
⑥:配置WWDT的计数值
该函数用于配置WWDT的计数值,也就是所谓的“喂狗”,其函数原型如下:
void WWDT_ConfigCounter(uint8_t counter);
该函数的形参描述,如下表所示:
形参 描述
counter WWDT的计数值
表15.2.1.9 函数WWDT_ConfigCounter()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表15.2.1.10 函数WWDT_ConfigCounter()返回值描述
该函数的使用示例,如下表所示:
#include "apm32f4xx.h"
#include "apm32f4xx_wwdt.h"
void example_fun(void)
{
/* 配置WWDT的计数值(喂狗) */
WWDT_ConfigCounter(0x7F);
}
15.2.2 看门狗驱动
本章实验的看门狗驱动主要负责向应用层提供WWDT的初始化函数,并实现WWDT的提前唤醒中断服务函数,在WWDT的提前唤醒中断服务函数中执行“喂狗”操作。本章实验中,看门狗的驱动代码包括wdt.c和wdt.h两个文件。
看门狗驱动中WWDT的初始化函数,如下所示:
/**
* @brief 窗口看门狗初始化
* @param tr: 计数器数值
* @param tw: 窗口值
* @param fprer: 时基预分频系数,WWDT_TIME_BASE_1~WWDT_TIME_BASE_8
* Fwwdt = (PCLK1 / 4096) / (2^fprer)
* @retval 无
*/
void wwdt_init(uint8_t tr, uint8_t wr, uint32_t fprer)
{
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_WWDT); /* 使能WWDT时钟 */
WWDT_Enable(tr); /* 使能窗口看门狗并设置计数器数值 */
WWDT_ConfigTimebase((WWDT_TIME_BASE_T)fprer); /* 配置时基预分频系数 */
WWDT_ConfigWindowData(wr); /* 设置窗口值 */
wwdt_counter = tr;
WWDT_EnableEWI(); /* 使能提前唤醒中断 */
NVIC_EnableIRQRequest(WWDT_IRQn, 2, 0); /* 使能中断 */
}
从上面的代码中可以看出,WWDT的初始化函数中除了使能了WWDT的时钟外,还分别执行了使能WWDT、配置WWDT的预分频系数和窗口值、使能WWDT的提前唤醒中断和使能WWDT中断的操作。随后,在WWDT计数值减少到0x40时,将会产生提前唤醒中断。
看门狗驱动中,WWDT提前唤醒中断的中断服务函数,如下所示:
/**
* @brief 窗口看门狗提前唤醒中断服务函数
* @param 无
* @retval 无
*/
void WWDT_IRQHandler(void)
{
if (WWDT_ReadFlag() == SET) /* 判断提前唤醒中断标志 */
{
WWDT_ConfigCounter(wwdt_counter); /* 重新配置窗口看门狗计数器数值 */
LED1_TOGGLE(); /* 翻转LED1状态 */
WWDT_ClearFlag(); /* 清除提前唤醒中断标志 */
}
}
可以看到,在窗口看门狗的提前唤醒中断服务函数中,对WWDT进行了喂狗操作,同时还对LED1的状态进行了以此翻转(方便观察)。
15.2.3 实验应用代码
本章实验的应用代码,如下所示:
int main(void)
{
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3); /* 设置中断优先级分组为组3 */
sys_apm32_clock_init(336, 8, 2, 7); /* 配置系统时钟 */
delay_init(168); /* 初始化延时功能 */
usart_init(115200); /* 初始化串口 */
led_init(); /* 初始化LED */
LED0(0); /* LED0点亮 */
delay_ms(300);
wwdt_init(0x7F, 0x5F, WWDT_TIME_BASE_8);
while (1)
{
LED0(1); /* LED0熄灭 */
}
}
可以看到应用代码中,LED初始化后,LED0会被点亮300毫秒,随后初始化窗口看门狗并熄灭LED0,若窗口看门狗没有正常被“喂狗”,那么程序复位,可以看到LED0再次亮起和熄灭,若窗口看门狗正常被“喂狗”,则可以看到LED1闪烁。
15.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0在上电时,亮起并熄灭一次,随后LED1不断闪烁,说明WWDT“喂狗”正常。