STM32 WWDG 窗口看门狗

本贴最后更新于 1628 天前,其中的信息可能已经时移世异

STM32 窗口看门狗简介

窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序正常的运行序列而产生的软件故障。除非递减计数器的值在 WWDG->CR 的第六位变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU 复位。在递减计数达到窗口配置寄存器(WWDG->CFR)数值之前,如果 7 位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个 MCU 复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。

STM32 有两个看门狗,一个是独立看门狗(IWDG)之前写过《STM32 IWDG 独立看门狗》,另一个是窗口看门狗(WWDG)。我们知道独立看门狗的工作原理就是一个键值寄存器(IWDG_KR)低 16 位寄存器。软件必须每隔一定时间写入 0xAAAA,否则,当计数器减到 0 时,程序会自动复位。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值 0X40 时还不喂狗的话,就会产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。

png

上窗口值(W[6:0]) 是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于 0X40,否则窗口就不存在了。

窗口看门狗的超时公式

TWWDG = (4096×2^WDGTB×(T[5:0]+1)) / FPCLK1;
TWWDG: WWDG 超时时间(单位为 ms)
FPCLK1: APB1 的时钟频率(单位为 Khz)
WDGTB: WWDG 的预分频系数
T[5:0]:窗口看门狗的计数器低 6 位

现在假设 FPCLK1 = 36 MHZ,那么就可以得到最小到最大超时时间表如下:

WDGTB 最小超时时间 最大超时时间
0 113 微秒 7.28 毫秒
1 227 微秒 14.56 毫秒
2 455 微秒 29.12 毫秒
3 910 微秒 58.25 毫秒

窗口看门狗 3 个重要的寄存器

WWDG 的第一个寄存器是控制寄存器(WWDG_CR)

WWDG_CRpng

它只有低八位有效, T[6: 0]用来存储看门狗的计数器值,随时更新的,每个窗口看门狗计数周期(4096×2^ WDGTB)减 1。当该计数器的值从 0X40 变为 0X3F 的时候,将产生看门狗复位。WDGA 位则是看门狗的激活位,该位由软件置 1,以启动看门狗,并且一定要注意的是该位一旦设置,就只能在硬件复位后才能清零了 。

WWDG 的第二个寄存器是配置寄存器(WWDG_CFR)

WWDG_CFR TODAY BLOG

WWDG_CFR 寄存器各位描述 TODAY BLOG

WWDG_CFR 中的 EWI 是提前唤醒中断,也就是在快要产生复位的前一段时间(T[6:0]=0X40) 来提醒我们,需要进行喂狗了,否则将复位!因此,我们一般用该位来设置中断,当窗口看门狗的计数器值减到 0X40 的时候,如果该位设置,并开启了中断,则会产生中断,我们可以在中断里面向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。注意这里在进入中断后, 必须在不大于 1 个窗口看门狗计数周期的时间(在 PCLK1 频率为 36M 且 WDGTB 为 0 的条件下,该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产生复位。

WWDG 的最后一个寄存器是状态寄存器(WWDG_SR),该寄存器是用来记录当前是否有唤醒的标志。该寄存器仅有第 0 位(从 0 开始计算)有效,其他都是保留位,当计数器值达到 0x40 时,此位由硬件置 1。它必须通过软件写 0 来清除。对此位写 1 无效。 即使中断未被使能, 在计数器的值达到 0X40 的时候, 此位也会被置 1。

在介绍完了窗口看门狗的寄存器之后,我们介绍要如何启用 STM32 的窗口看门狗。 这里我们介绍库函数中用中断的方式来喂狗的方法,WWDG 库函数相关源码和定义分布在源文件 stm32f10x_wwdg.c 文件和头文件 stm32f10x_wwdg.h

一般步骤

使能 WWDG 时钟
设置窗口值和分频数
开启 WWDG 中断并分组
设置计数器初始值并使能看门狗
编写中断服务函数

硬件设计

指示灯 DS0 和 DS1,通过 DS0 和 DS1 来指示 STM32 的复位情况和窗口看门狗的喂狗情况。

软件设计

png
wwdg.h
WWDG_H

#ifndef __WDG_H
#define __WDG_H

#include <stm32f10x.h>
 
void WWDG_Init(u8 tr,u8 wr,u32 fprer);//初始化WWDG
void WWDG_Set_Counter(u8 cnt);       //设置WWDG的计数器
void WWDG_NVIC_Init(void);            
 
#endif

wwdg.c

Today_20180515_213813png

#include "wwdg.h"
#include <misc.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_wwdg.h>
#include "../led/led.h"
 
u8 WWDG_CNT = 0x7f;

void WWDG_Init(u8 tr, u8 wr, u32 fprer) {
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);  //WWDG时钟使能
 
    WWDG_SetPrescaler(fprer);        //设置IWDG预分频值
    WWDG_SetWindowValue(wr);         //设置窗口值
    WWDG_Enable(tr);                 //使能看门狗,设置 counter.
    WWDG_ClearFlag();
    WWDG_NVIC_Init();                //初始化窗口看门狗 NVIC
    WWDG_EnableIT();                 //开启窗口看门狗中断
}
 
//窗口看门狗中断服务程序
void WWDG_NVIC_Init() {
 
    NVIC_InitTypeDef NVIC_InitTypeDef;
    NVIC_InitTypeDef.NVIC_IRQChannel                    = WWDG_IRQn; //WWDG中断
    NVIC_InitTypeDef.NVIC_IRQChannelPreemptionPriority  = 2;        //抢占2,子优先级3,组2
    NVIC_InitTypeDef.NVIC_IRQChannelSubPriority         = 3;        //抢占2,子优先级3,组2
    NVIC_InitTypeDef.NVIC_IRQChannelCmd                 = ENABLE;
  
    NVIC_Init(&NVIC_InitTypeDef);                                   //NVIC初始化
}
void WWDG_IRQHandler(void) {
    WWDG_SetCounter(0x7F);    //当禁掉此句后,窗口看门狗将产生复位
    WWDG_ClearFlag();     //清除提前唤醒中断标志位
    LED1=!LED1;
}

main.c

Today_20180515_213925png

#include <misc.h>

#include <stm32f10x_wwdg.h>

 

#include "delay/delay.h"

#include "led/led.h"
#include "wwdg/wwdg.h"
 
int main(int argc, char **argv) {
 
    delay_init();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断优先级分组2
    LED_Init();
    LED0 = 0;
    WWDG_Init(0X7F, 0X5F, WWDG_Prescaler_8);
    while (1) {
        LED0 = !LED0;
        delay_ms(1000);
    }
}

效果:系统上电后 LED0 每隔 1000ms 闪烁一次,LED1 会在喂狗时闪烁。

1 操作
Today 在 2020-06-08 09:31:03 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • Today
    作者

    你可以按照我上面的例子写一下,主循环还是要写点东西的 😄

  • 其他回帖
  • leifayu

    仔细测试了一下,问题出在 WWDG 的中断服务函数里面。在中断服务函数里面必须要干点活才能避免复位,如果仅仅是喂狗、清标志,就不可避免要被复位。
    这个我可能要看看编译之后的汇编代码了,看看逻辑是咋走的。

    void WWDG_IRQHandler(void)
    {
        static uint32_t c = 0;
        
        WWDG_SetCounter(0x7F);
        WWDG_ClearFlag();
    
    #if defined(__LED_TOGGLE_IN_WWDG__)    
        c ++;
        if (0 == c%20) // WWDG最长大约54ms
        {
            LED_TOGGLE();
        }
    #else
        // 多少干些事情,看看啥情况
        c ++;
        if (1000 < c)
            c = 0;
    #endif
    }
    
    1 回复
  • Today
    作者

    一般中断要尽可能快的出来,不要耗费太多时间

  • leifayu

    你好,我看了网上很多人都说在 WWDG 的中断里面喂狗可以避免复位。我尝试这么做了,实际上还是复位了。我就奇怪大家是怎么做的?为什么到我手上就是不行呢?CUsersleifayuDesktop 微信图片 20200605163736.png

    1 回复
  • 查看全部回帖

推荐标签 标签

  • OnlyOffice
    4 引用 • 2 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    6 引用 • 63 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 431 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 529 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 22 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 462 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    98 引用 • 344 回帖
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    407 引用 • 1246 回帖 • 582 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 113 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    351 引用 • 1814 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 16 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    69 引用 • 373 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 536 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    110 引用 • 54 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 672 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 210 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 709 关注
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 1 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    77 引用 • 390 回帖
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 529 关注
  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖 • 8 关注
  • 电影

    这是一个不能说的秘密。

    120 引用 • 599 回帖