打印
[其他ST产品]

窗口看门狗(WWDG)详解

[复制链接]
楼主: 根特皇宫w
手机看帖
扫描二维码
随时随地手机跟帖
21
根特皇宫w|  楼主 | 2022-11-30 18:55 | 只看该作者 回帖奖励 |倒序浏览
    该寄存器用来记录当前是否有提前唤醒的标志。该寄存器仅有位 0 有效,其他都是保留位。当计数器值达到 40h 时,此位由硬件置 1。 它必须通过软件写 0 来清除。对此位写 1 无效。即使中断未被使能,在计数器的值达到 0X40的时候,此位也会被置 1。

使用特权

评论回复
22
根特皇宫w|  楼主 | 2022-11-30 18:56 | 只看该作者
WWDG固件库函数

       窗口看门狗库函数相关源码和定义分布在文件 stm32f10x_wwdg.c 文件和头文件 stm32f10x_wwdg.h 中。

使用特权

评论回复
23
根特皇宫w|  楼主 | 2022-11-30 18:57 | 只看该作者
使能 WWDG 时钟

WWDG 不同于IWDG,IWDG 有自己独立的 40Khz 时钟,不存在使能问题。而 WWDG使用的是 PCLK1 的时钟,需要先使能时钟。方法是:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能

使用特权

评论回复
24
根特皇宫w|  楼主 | 2022-11-30 18:58 | 只看该作者
设置窗口值和分频数

        设置窗口值的函数是:

void WWDG_SetWindowValue(uint8_t WindowValue);

使用特权

评论回复
25
根特皇宫w|  楼主 | 2022-11-30 18:58 | 只看该作者
   这个函数的入口参数 WindowValue 用来设置看门狗的上窗口值。

        设置分频数的函数是:

void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);

使用特权

评论回复
26
根特皇宫w|  楼主 | 2022-11-30 18:59 | 只看该作者
这个函数同样只有一个入口参数,用来设置看门狗的分频值。

使用特权

评论回复
27
根特皇宫w|  楼主 | 2022-11-30 18:59 | 只看该作者
开启 WWDG 中断并分组

        开启 WWDG 中断的函数为:

WWDG_EnableIT(); //开启窗口看门狗中断

        接下来是进行中断优先级配置,这里就不重复了,使用 NVIC_Init()函数即可。

使用特权

评论回复
28
根特皇宫w|  楼主 | 2022-11-30 19:00 | 只看该作者
设置计数器初始值并使能看门狗

        这一步在库函数里面是通过一个函数实现的:

void WWDG_Enable(uint8_t Counter);

        该函数既设置了计数器初始值,同时使能了窗口看门狗。

使用特权

评论回复
29
根特皇宫w|  楼主 | 2022-11-30 19:01 | 只看该作者
编写中断服务函数

        编写窗口看门狗的中断服务函数,通过该函数来喂狗,必须在不大于 1 个窗口看门狗计数周期的时间内完成喂狗,否则当窗口看门狗计数器值减到 0X3F 的时候,就会引起软复位了。在中断服务函数里面也要将状态寄存器的 EWIF 位清空。

使用特权

评论回复
30
根特皇宫w|  楼主 | 2022-11-30 19:02 | 只看该作者
WWDG(窗口看门狗)实验

硬件设计

        1) 指示灯 DS0 和 DS1

        2) 窗口看门狗

        窗口看门狗属于 STM32 的内部资源,只需要软件设置好即可正常工作。我们通过 DS0 和 DS1 来指示 STM32 的复位情况和窗口看门狗的喂狗情况。

使用特权

评论回复
31
根特皇宫w|  楼主 | 2022-11-30 19:03 | 只看该作者
软件设计

        在工程文件目录下面新建两个文件夹分别为:wdg.c和wdg.h。并在把源文件添加到工程,和添加头文件的路径。

使用特权

评论回复
32
根特皇宫w|  楼主 | 2022-11-30 19:03 | 只看该作者
wdg.c 里面的代码如下:
#include "wdg.h"
#include "led.h"


void IWDG_Init(u8 prer,u16 rlr)
{       
        IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  //使能对寄存器IWDG_PR和IWDG_RLR的写操作
       
        IWDG_SetPrescaler(prer);  //设置IWDG预分频值:设置IWDG预分频值为64
       
        IWDG_SetReload(rlr);  //设置IWDG重装载值
       
        IWDG_ReloadCounter();  //按照IWDG重装载寄存器的值重装载IWDG计数器
       
        IWDG_Enable();  //使能IWDG
}
//喂独立看门狗
void IWDG_Feed(void)
{   
        IWDG_ReloadCounter();        //重载计数值                                                                          
}


//保存WWDG计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
//初始化窗口看门狗        
//tr   :T[6:0],计数器值
//wr   :W[6:0],窗口值
//fprer:分频系数(WDGTB),仅最低2位有效
//Fwwdg=PCLK1/(4096*2^fprer).

void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //   WWDG时钟使能

        WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.   
        WWDG_SetPrescaler(fprer);设置IWDG预分频值

        WWDG_SetWindowValue(wr);//设置窗口值

        WWDG_Enable(WWDG_CNT);         //使能看门狗 ,        设置 counter .                  

        WWDG_ClearFlag();//清除提前唤醒中断标志位

        WWDG_NVIC_Init();//初始化窗口看门狗 NVIC

        WWDG_EnableIT(); //开启窗口看门狗中断
}
//重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
{
    WWDG_Enable(cnt);//使能看门狗 ,        设置 counter .         
}
//窗口看门狗中断服务程序
void WWDG_NVIC_Init()
{
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;    //WWDG中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   //抢占2,子优先级3,组2       
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         //抢占2,子优先级3,组2       
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);//NVIC初始化
}

void WWDG_IRQHandler(void)
        {

        WWDG_SetCounter(WWDG_CNT);          //当禁掉此句后,窗口看门狗将产生复位

        WWDG_ClearFlag();          //清除提前唤醒中断标志位

        LED1=!LED1;                 //LED状态翻转
        }

使用特权

评论回复
33
根特皇宫w|  楼主 | 2022-11-30 19:04 | 只看该作者
   第一个函数 void WWDG_Init(u8 tr,u8 wr,u8 fprer)用来设置 WWDG 的初始化值。包括看门狗计数器的值和看门狗比较值等。全局变量 WWDG_CNT,该变量用来保 存最初设置 WWDG_CR 计数器的值。在后续的中断服务函数里面,就又把该数值放回到WWDG_CR 上。

使用特权

评论回复
34
根特皇宫w|  楼主 | 2022-11-30 19:05 | 只看该作者
  第二个函数WWDG_Set_Counter()是用来重设窗口看门狗的计数器值的。

使用特权

评论回复
35
根特皇宫w|  楼主 | 2022-11-30 19:05 | 只看该作者
第三个函数是中断分组函数。

使用特权

评论回复
36
根特皇宫w|  楼主 | 2022-11-30 19:06 | 只看该作者
第四个函数是中断服务函数,先重设窗口看门狗的计数器值,然后清除提前唤醒中断标志。函数中也对 LED1(DS1)取反,来监测中断服务函数的执行了状况。

使用特权

评论回复
37
根特皇宫w|  楼主 | 2022-11-30 19:07 | 只看该作者
wdg.h 里面的代码如下:

    #ifndef __WDG_H
    #define __WDG_H
    #include "sys.h"
              
     
     
    void IWDG_Init(u8 prer,u16 rlr);
    void IWDG_Feed(void);
     
    void WWDG_Init(u8 tr,u8 wr,u32 fprer);//初始化WWDG
    void WWDG_Set_Counter(u8 cnt);       //设置WWDG的计数器
    void WWDG_NVIC_Init(void);
     
    #endif

使用特权

评论回复
38
根特皇宫w|  楼主 | 2022-11-30 19:07 | 只看该作者
      把头文件中的几个函数名加入到头文件里面去,其他文件的文件可以调用。

使用特权

评论回复
39
根特皇宫w|  楼主 | 2022-11-30 19:08 | 只看该作者
main.c中的代码:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "wdg.h"


int main(void)
{               
        delay_init();                     //延时函数初始化          
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
        uart_init(115200);         //串口初始化为115200
        LED_Init();
        KEY_Init();          //按键初始化         
        LED0=0;
        delay_ms(300);          
        WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8);//计数器值为7f,窗口寄存器为5f,分频数为8          
        while(1)
        {
                LED0=1;                                    
        }   
}

使用特权

评论回复
40
根特皇宫w|  楼主 | 2022-11-30 19:08 | 只看该作者
该函数通过 LED0(DS0)来指示是否正在初始化。而 LED1(DS1)用来指示是否发生了中 断。我们先让 LED0 亮 300ms,然后关闭以用于判断是否有复位发生了。在初始化 WWDG 之后,我们回到死循环,关闭 LED1,并等待看门狗中断的触发/复位。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则