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 例程功能
表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“喂狗”正常。