【正点原子STM32连载】 第十五章 窗口看门狗实验 摘自【正点原子】APM32E103最小系统板使用指南

2023-12-16 19:50:04

1)实验平台:正点原子APM32E103最小系统板
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban

第十五章 窗口看门狗实验

本章介绍APM32E103窗口看门狗(WWDT)的使用,窗口看门狗与独立看门狗一样能够帮助CPU在进入错误状态或程序跑飞时进行复位,不过窗口看门狗相对于独立看门狗限制了“喂狗”的最小间隔,若两次“喂狗”的间隔太短,一样会产生复位。通过本章的学习,读者将学习到WWDT的使用。
本章分为如下几个小节:
15.1 硬件设计
15.2 程序设计
15.3 下载验证

15.1 硬件设计
15.1.1 例程功能

  1. 程序运行后,点亮LED0等待300毫秒后开启窗口看门狗,后进入死循环等待窗口看门狗的中断在窗口看门狗的中断服务函数中执行喂狗和翻转LED1状态的操作,能观察到的现象为LED0在程序启动时闪烁以下,随后LED1不停闪烁
    15.1.2 硬件资源
  2. LED
    LED0 - PB5
    LED1 - PE5
  3. 窗口看门狗
    15.1.3 原理图
    本章实验使用的窗口看门狗为APM32E103的片上资源,因此并没有相应的连接原理图。
    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);
    该函数的形参描述,如下表所示:
    形参 描述
    counter WWDT的计数值
    该值从0x40减到0x3F时,会产生WWDT复位
    表15.2.1.1 函数WWDT_Enable()形参描述
    该函数的返回值描述,如下表所示:
    返回值 描述
    无 无
    表15.2.1.2 函数WWDT_Enable()返回值描述
    该函数的使用示例,如下所示:
#include "apm32e10x.h"
#include "apm32e10x_wwdt.h"

void example_fun(void)
{
    /* 使能WWDT */
    WWDT_Enable(0x7F);
}

②:配置WWDT预分频系数
该函数用于配置WWDT的预分频系数,预分频系数决定了WWDT计数的快慢,其函数原型如下所示:
void WWDT_ConfigTimebase(WWDT_TIME_BASE_T timeBase);
该函数的形参描述,如下表所示:
形参 描述
timeBase WWDT的时基预分频值
例如:WWDT_TIME_BASE_1、WWDT_TIME_BASE_2等(在apm32e10x _wwdt.h文件中有定义)
表15.2.1.3 函数WWDT_ConfigTimebase()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表15.2.1.4 函数WWDT_ConfigTimebase()返回值描述
该函数的使用示例,如下所示:

#include "apm32e10x.h"
#include "apm32e10x_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 "apm32e10x.h"
#include "apm32e10x_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 "apm32e10x.h"
#include "apm32e10x_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 "apm32e10x.h"
#include "apm32e10x_wwdt.h"

void example_fun(void)
{
    /* 配置WWDT的计数值(喂狗) */
    WWDT_ConfigCounter(0x7F);
}

15.2.2 看门狗驱动
本章实验的看门狗驱动主要负责向应用层提供WWDT的初始化函数,并实现WWDT的提前唤醒中断服务函数,在WWDT的提前唤醒中断服务函数中执行“喂狗”操作。本章实验中,看门狗驱动的驱动代码包括wdt.c和wdt.h两个文件。
看门狗驱动中WWDT的初始化函数,如下所示:


```c
/**
 * @brief       初始化窗口看门狗
 * @param       tr: T[5:0],计数器值
 * @param       tw: W[6:0],窗口值
 * @param       fprer:分频系数(WDGTB),范围:WWDT_TIME_BASE_1~WWDT_TIME_BASE_8,
                      表示2^WDGTB分频
 *              Twwdt=TPCLK1 * 2^(WTB) * (T[5:0]+1). 一般PCLK1 = 60MHz
                最大-最小超时时间参考《APM32E103xCxE用户手册 V1.3》 第十八章
 * @retval      无
 */
void wwdt_init(uint8_t tr, uint8_t tw, WWDT_TIME_BASE_T fprer)
{
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_WWDT);/* 打开时钟 */
    wwdt_cnt = tr;                                  /* 初始化wwdt_cnt传进参数tr*/
    WWDT_ConfigTimebase(fprer);                     /* 设置WWDT分频系数 */
    WWDT_ConfigWindowData(tw);                      /* 窗口值 */
    WWDT_Enable(tr);                                /* 设置计数器的值,使能WWDT */
    WWDT_ClearFlag();                               /* 清楚唤醒中断标志位 */
    wwdt_nvic_init();                               /* 窗口看门狗中断初始化 */
    WWDT_EnableEWI();                               /* 使能窗口看门狗中断 */
}

从上面的代码中可以看出,WWDT的初始化函数中除了使能WWDT的时钟外,还分别执行了使能WWDT、配置WWDT的预分频系数和窗口值、使能WWDT的提前唤醒中断和使能WWDT中断的操作。随后,在WWDT计数值减少到0x40时,将会产生提前唤醒中断。

```c
/**
 * @brief       窗口看门狗中断服务程序
 * @param       无
 * @retval      无
 */
void WWDT_IRQHandler(void)
{
    if (WWDT_ReadFlag() != RESET)
    {
        WWDT_ConfigCounter(wwdt_cnt);/* 刷新递减计数器的值,当计数器值小于窗口值喂狗 */
        LED1_TOGGLE();               /* LED1闪烁 */
        WWDT_ClearFlag();            /* 清楚唤醒中断标志位 */
    }
}

从上面的代码中可以看出,在窗口看门狗的提前唤醒中断服务函数中,对WWDT进行了喂狗操作,同时LED1的亮灭状态发生了翻转。通过代码设置LED1亮灭状态翻转的目的在于方便观察“喂狗”这一过程。
15.2.3 实验应用代码
本实验的应用代码,如下所示:

int main(void)
{
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_4);  /* 设置中断优先级分组为组4 */
    sys_apm32_clock_init(15);                         /* 配置系统时钟 */
    delay_init(120);                                  /* 初始化延时功能 */
    usart_init(115200);                               /* 初始化串口 */
    led_init();                                       /* 初始化LED */
    LED0(0);                                          /* 先点亮LED0 */
    delay_ms(500);                                    /* 延时500ms */
    wwdt_init(0x7F, 0x5F, WWDT_TIME_BASE_8);          /* 初始化窗口看门狗 */
    
    while (1)
    {
        LED0(1);                                      /* 关闭LED0 */
    }
}

从上面的代码中可以看出,初始化LED后,LED0会被点亮500毫秒,随后初始化窗口看门狗并熄灭LED0,若窗口看门狗没有正常被“喂狗”,那么程序复位,可以看到LED0再次亮起和熄灭,如果窗口看门狗被正常“喂狗”,则可以看到LED1快速闪烁。
15.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0在上电时,亮起并熄灭一次,随后LED1不断闪烁,说明WWDT“喂狗”正常。

文章来源:https://blog.csdn.net/weixin_55796564/article/details/135034241
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。