STM32独立看门狗

时钟频率

40KHZ

看门狗简介

STM32F10xxx 内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看
门狗设备 ( 独立看门狗和窗口看门狗 ) 可用来检测和解决由软件错误引起的故障;当计数器达到给
定的超时值时,触发一个中断 ( 仅适用于窗口型看门狗 ) 或产生系统复位。
独立看门狗 (IWDG) 由专用的 40kHz 的低速时钟驱动,即使主时钟发生故障它也仍然有效。窗口
看门狗由从 APB1 时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的
过迟或过早的操作。
IWDG 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精
度要求较低的场合。 WWDG 最适合那些要求看门狗在精确计时窗口起作用的应用程序。

IWDG主要性能

● 自由运行的递减计数器
● 时钟由独立的 RC 振荡器提供 ( 可在停止和待机模式下工作 )
● 看门狗被激活后,则在计数器计数至 0x000 时产生复位

IWDG功能描述

在键寄存器 (IWDG_KR) 中写入 0xCCCC ,开始启用独立看门狗;此时计数器开始从其复位值
0xFFF 递减计数。当计数器计数到末尾 0x000 时,会产生一个复位信号 (IWDG_RESET)
无论何时,只要键寄存器 IWDG_KR 中被写入 0xAAAA IWDG_RLR 中的值就会被重新加载到
计数器中从而避免产生看门狗复位 。

键寄存器(IWDG_KR)

预分频寄存器(IWDG_PR)

重装载寄存器(IWDG_RLR)

IWDG库函数

看门狗蜂鸣器

main.c


/*看门狗*/
#include"iwdg.h"
#include"led.h"
#include"fmq.h"
#include"key.h"
#include"delay.h"

int main(void)
{
	int i=0,j=0;
	Led_Init();	
	Key_Init();
	Fmq_Init();
	delay_init();
	iwdg_init(5);
	Fmq_On();
	delay_ms(2000);
	Fmq_Off();
	for(i=0;i<3;i=(i+1)%3)
	{
		iwdg_fee_dog();
		Led_On(i);
		delay_ms(500);
		Led_Off(i);
		delay_ms(500);
	}
	return 0;
}





iwdg.h

#ifndef _IWDG_H
#define _IWDG_H
#include "stm32f10x_conf.h"
extern void iwdg_init(int nu);
extern void iwdg_fee_dog(void);
#endif

iwdg.c

#include"iwdg.h"

void iwdg_init(int nu) 
{
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //关闭寄存器写保护 
    IWDG_SetPrescaler(IWDG_Prescaler_64); //625设置预分频值
    IWDG_SetReload(nu*625); //设置重装载值
    IWDG_ReloadCounter(); //重载计数值喂狗
    IWDG_Enable(); //启动关门狗
}

void iwdg_fee_dog(void)
{ 
    IWDG_ReloadCounter();//喂狗
}

delay.c

#include "delay.h"

//利用系统滴答定时,编写的延时函数

static u8  fac_us=0; //us延时倍乘数			   
static u16 fac_ms=0; //ms延时倍乘数

/****************************************************************************
* 名    称: delay_init()
* 功    能:延时函数初始化
* 入口参数:无
* 返回参数:无
* 说    明:
****************************************************************************/
void delay_init(void)
{
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
	//为系统定时器选择时钟为	HCLK 8分频	72MHz / 8 = 9MHz
	fac_us = SYSCLK / 8;
	//微秒的倍乘数 = 72 / 8 = 9
	//X * fac_us就相当于有X个微妙
	fac_ms = (u16)fac_us * 1000; 
	//每个ms需要的systick时钟数(1ms = 1000us),所以fac_us*1000
	//X * fac_ms就相当于有X个毫妙
}								    

/****************************************************************************
* 名    称: void delay_us(u32 nus)
* 功    能:延时nus
* 入口参数:要延时的微秒数
* 返回参数:无
* 说    明:nus的值,不要大于1864135us
****************************************************************************/
/*
通过相关手册我们了解到,备份值寄存器和当前值寄存器的值最大为16M - 1
我们的微秒级的延时函数的倍乘数为9所以16M - 1 / 9 = 1864135
*/
void delay_us(u32 nus)
{
	u32 midtime;																			//保存寄存器的状态
	SysTick->LOAD = nus * fac_us;											//时间加载(相当于有nus个微妙)
	SysTick->VAL = 0x00;															//清空计数器
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;					//使能系统定时器计数
	do
	{
		midtime = SysTick->CTRL;
	}
	while((midtime & 0x01) && !(midtime & (1 << 16)));//等待时间到达
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;				//关闭计数器
	SysTick->VAL = 0X00;															//清空计数器	 
}
/****************************************************************************
* 名    称: void delay_xms(u16 nms)
* 功    能:延时nms
* 入口参数:要延时的毫妙数
* 返回参数:无
* 说    明:SysTick->LOAD为24位寄存器,所以,最大延时为: nms<=0xffffff*8*1000/SYSCLK
            对9M条件下,nms<=1864ms 
****************************************************************************/
void delay_xms(u16 nms)
{	 		  	  
	u32 midtime;		   
	SysTick->LOAD = (u32)nms*fac_ms;									//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL = 0x00;															//清空计数器
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;					//开始倒数
	do
	{
		midtime = SysTick->CTRL;
	}
	while((midtime & 0x01) && !(midtime & (1 << 16)));//等待时间到达
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;				//关闭计数器
	SysTick->VAL = 0X00;															//清空计数器
} 
/****************************************************************************
* 名    称: void delay_ms(u16 nms)
* 功    能:延时nms
* 入口参数:要延时的毫妙数
* 返回参数:无
* 说    明:nms:0~65535
****************************************************************************/
void delay_ms(u16 nms)
{	 	 
	u8 repeat = nms / 540;	//记录有多少个整的540ms
	u16 remain = nms % 540;	//记录有多少个不够540ms
	while(repeat)
	{
		delay_xms(540);
		repeat--;
	}
	if(remain)delay_xms(remain);
} 


delay.h

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f10x_conf.h" 

#define SYSCLK 72				//系统时钟的基数(注:是72而不是72M)

typedef uint32_t  u32;
typedef uint16_t  u16;
typedef uint8_t   u8;
	
void delay_init(void);	//延时函数的初始化
void delay_ms(u16 nms);	//毫秒级的延时函数(参数为毫秒数)
void delay_us(u32 nus);	//微秒级的延时函数(参数为微秒数)

#endif
















fmq.h

#ifndef __FMQ_H
#define __FMQ_H
#include "stm32f10x_conf.h"
extern void Fmq_Init(void);//初始化FMQ
extern void Fmq_On(void);//蜂鸣器响
extern void Fmq_Off(void);//蜂鸣器不响
#endif 

fmq.c

#include"key.h"
void Key_Init(void)
{
	GPIO_InitTypeDef GPIO_VALUE; 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_VALUE.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_VALUE.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_8;
	GPIO_Init(GPIOC,&GPIO_VALUE);	
	
	GPIO_VALUE.GPIO_Mode=GPIO_Mode_IPD;
	GPIO_VALUE.GPIO_Pin=GPIO_Pin_0;
	GPIO_Init(GPIOC,&GPIO_VALUE);	
}
int Key_status(int nu)
{
	int ret=0;
	switch(nu)
	{
		case 0:ret=GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9);break;
		case 1:ret=GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8);break;
		case 2:ret=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);ret=!ret;break;
	}
	return !ret;
	
}

led.h

#ifndef __LED_H
#define __LED_H
#include "stm32f10x_conf.h"

extern void Led_Init(void);
extern void Led_On(int opt);
extern void Led_Off(int opt);
#endif 

led.c


#include"led.h"

void Led_Init(void)
{
	GPIO_InitTypeDef GPIO_VALUE; //???
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???
	GPIO_VALUE.GPIO_Mode=GPIO_Mode_Out_PP;//???? ????
	GPIO_VALUE.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;//????
	GPIO_VALUE.GPIO_Speed=GPIO_Speed_50MHz;//????
	GPIO_Init(GPIOC,&GPIO_VALUE);//???	
}
void Led_On(int nu)
{
	switch(nu)
	{
		case 0:GPIO_SetBits(GPIOC,GPIO_Pin_1);break;
		case 1:GPIO_SetBits(GPIOC,GPIO_Pin_2);break;
		case 2:GPIO_SetBits(GPIOC,GPIO_Pin_3);break;
	}
		
}
void Led_Off(int nu)
{
	switch(nu)
	{
		case 0:GPIO_ResetBits(GPIOC,GPIO_Pin_1);break;
		case 1:GPIO_ResetBits(GPIOC,GPIO_Pin_2);break;
		case 2:GPIO_ResetBits(GPIOC,GPIO_Pin_3);break;
	}	
}










/*
#include"led.h"
#include"bitband.h"
void Led_Init(void)
{
	GPIO_InitTypeDef GPIO_VALUE; //???
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???
	GPIO_VALUE.GPIO_Mode=GPIO_Mode_Out_PP;//???? ????
	GPIO_VALUE.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;//????
	GPIO_VALUE.GPIO_Speed=GPIO_Speed_50MHz;//????
	GPIO_Init(GPIOC,&GPIO_VALUE);//???	
}
void Led_On(int nu)
{
	switch(nu)
	{
		case 0:PCOut(1)=1;break;
		case 1:PCOut(2)=1;break;
		case 2:PCOut(3)=1;break;
	}
		
}
void Led_Off(int nu)
{
	switch(nu)
	{
		case 0:PCOut(1)=0;break;
		case 1:PCOut(2)=0;break;
		case 2:PCOut(3)=0;break;
	}	
}
*/

main.c


/*看门狗*/
#include"iwdg.h"
#include"led.h"
#include"fmq.h"
#include"key.h"
#include"delay.h"

int main(void)
{
	int i=0,j=0;
	Led_Init();	
	Key_Init();
	Fmq_Init();
	delay_init();
	iwdg_init(5);
	Fmq_On();
	delay_ms(2000);
	Fmq_Off();
	for(i=0;i<3;i=(i+1)%3)
	{
		iwdg_fee_dog();
		Led_On(i);
		delay_ms(500);
		Led_Off(i);
		delay_ms(500);
	}
	return 0;
}





看门狗过程

 1)取消寄存器写保护(向 IWDG_KR 写入 0X5555)

通过这步,我们取消 IWDG_PR 和 IWDG_RLR 的写保护,使后面可以操作这两个寄存器,设置 IWDG_PR 和 IWDG_RLR 的值。这在库函数中的实现函数是:

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
这个函数的功能开启/取消写保护,即使能/失能写权限。

        2)设置独立看门狗的预分频系数和重装载值

        设置看门狗的分频系数的函数是:

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //设置 IWDG 预分频值
        设置看门狗的重装载值的函数是:

        

void IWDG_SetReload(uint16_t Reload); //设置 IWDG 重装载值
        设置好看门狗的分频系数 prer 和重装载值就可以知道看门狗的喂狗时间(也就是看门狗溢出时间),该时间的计算方式为:

                                                        Tout=((4×2^prer) ×rlr) /40

        其中 Tout 为看门狗溢出时间(单位为 ms);prer 为看门狗时钟预分频值(IWDG_PR 值),范围为 0~7;rlr 为看门狗的重装载值(IWDG_RLR 的值);

        比如我们设定 prer 值为 4,rlr 值为 625,那么就可以得到 Tout=64×625/40=1000ms,这样,看门狗的溢出时间就是 1s,只要你在一秒钟之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。这里需要提醒大家的是,看门狗的时钟不是准确的 40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。

        3)重载计数值喂狗(向 IWDG_KR 写入 0XAAAA)

        库函数里面重载计数值的函数是:

IWDG_ReloadCounter(); //按照 IWDG 重装载寄存器的值重装载 IWDG 计数器
        通过这句,将使 STM32 重新加载 IWDG_RLR 的值到看门狗计数器里面。即实现独立看门狗的喂狗操作。

        4) 启动看门狗(向IWDG_KR 写入 0XCCCC)

        库函数里面启动独立看门狗的函数是:

IWDG_Enable(); //使能 IWDG
        通过这句,来启动 STM32 的看门狗。

        注意 IWDG 在一旦启用,就不能再被关闭!想要关闭,只能重启,并且重启之后不能打开 IWDG,否则问题依旧,如果不用 IWDG 的话,就不要去打开它,免得麻烦。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/271193.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WU反走样算法

WU反走样算法 由离散量表示连续量而引起的失真称为走样&#xff0c;用于减轻走样现象的技术成为反走样&#xff0c;游戏中称为抗锯齿。走样是连续图形离散为想想点后引起的失真&#xff0c;真实像素面积不为 零。走样是光栅扫描显示器的一种固有现象&#xff0c;只能减轻&…

Drogon Win11 编译 /MT

Drogon是一个基于C17/20的Http应用框架&#xff0c;使用Drogon可以方便的使用C构建各种类型的Web应用服务端程序。 Drogon的主要应用平台是Linux&#xff0c;也支持Mac OS、FreeBSD和Windows。 它的主要特点如下&#xff1a; 网络层使用基于epoll(macOS/FreeBSD下是kqueue)的…

nginx反向代理服务器及负载均衡服务配置

一、正向代理与反向代理 正向代理&#xff1a;是一个位于客户端和原始服务器(oricin server)之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向代理发送一个请求并指定目标(原始服务器)&#xff0c;然后代理向原始服务器转交请求并将获得的内容返回给客户…

Matlab/Simulink的一些功能用法笔记(3)

01--引言 最近加入到一个项目组&#xff0c;有一些测试需要去支持&#xff0c;通过了解原先团队的测试方法后&#xff0c;自己作了如下改善&#xff0c;大大提高了工作效率。这也许就是软件开发的意义吧&#xff0c;能够去除一些重复的机械的人工操作并且结果还非常不可靠。 …

Discrete Time Signals and Systems

Discrete Time Signals and Systems 文章目录 Discrete Time Signals and SystemsSignal classificationbasic signalOperation on signalSystem of discrete signalLinear systems and nonlinear systemsCausal and non-causal SystemsTime-varying and time-invariant system…

助力打造清洁环境,基于美团最新YOLOv6-4.0开发构建公共场景下垃圾堆放垃圾桶溢出检测识别系统

公共社区环境生活垃圾基本上是我们每个人每天几乎都无法避免的一个问题&#xff0c;公共环境下垃圾投放点都会有固定的值班时间&#xff0c;但是考虑到实际扔垃圾的无规律性&#xff0c;往往会出现在无人值守的时段内垃圾堆放垃圾桶溢出等问题&#xff0c;有些容易扩散的垃圾比…

使用travelbook架设自己的实时位置共享服务

travelbook 是一款开源的安卓APP&#xff0c;它能以低功耗提供实时位置共享&#xff0c;它包含功能如下&#xff1a; 好友之间分享实时位置&#xff1b;记录行程轨迹&#xff1b;标记收藏地点&#xff1b; 这款软件的主要解决的问题包括&#xff1a; 场景1&#xff1a;查看老…

【开源】基于Vue+SpringBoot的新能源电池回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

安防视频云平台/可视化监控云平台EasyCVR如何快速定位占用大量存储空间的文件?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

【Vue2+3入门到实战】(4)Vue基础之指令修饰符 、v-bind对样式增强的操作、v-model应用于其他表单元素 详细示例

目录 一、今日学习目标1.指令补充 二、指令修饰符1.什么是指令修饰符&#xff1f;2.按键修饰符3.v-model修饰符4.事件修饰符 三、v-bind对样式控制的增强-操作class1.语法&#xff1a;2.对象语法3.数组语法4.代码练习 四、京东秒杀-tab栏切换导航高亮1.需求&#xff1a;2.准备代…

小白的实验室服务器深度学习环境配置指南

安装nvidia 本文在ubuntu server 22.04上实验成功&#xff0c;其他版本仅供参考 注意&#xff0c;本文仅适用于ubuntu server&#xff0c;不需要图形界面&#xff0c;没有对图形界面进行特殊考虑和验证&#xff01;依赖图形操作界面的读者慎用 查看是否安装了gcc gcc -v若没…

如何快速删除pdf周围的空白

问题&#xff1a;写论文往往需要pdf格式的图片&#xff0c;但pdf往往四周存在大量空白需要手动截图很麻烦 解决&#xff1a; 打开命令行输入&#xff1a;pdfcrop 图片名.pdf

【Mysql】InnoDB统计数据的收集(十三)

我们前边在计算查询成本的时候会用到一些统计数据&#xff0c;比如通过 SHOW TABLE STATUS 可以看到关于表的统计数据&#xff0c;通过 SHOW INDEX 可以看到关于某个索引的统计数据&#xff0c;那么这些统计数据是怎么来的呢&#xff1f;本章节将分享 InnoDB 存储引擎的统计数据…

深圳锐科达SIP矿用电话模块SV-2801VP

深圳锐科达SIP矿用电话模块SV-2801VP 一、简介 SV-2800VP系列模块是我司设计研发的一款用于井下的矿用IP音频传输模块&#xff0c;可用此模块打造一套低延迟、高效率、高灵活和多扩展的IP矿用广播对讲系统&#xff0c;亦可对传统煤矿电话系统加装此模块&#xff0c;进行智能化…

在Vue3中使用vue-qrcode库实现二维码生成

本文主要介绍在Vue3中使用qrcode库实现二维码生成的方法。 目录 一、基础用法实现vue-qrcode库的参数介绍 在Vue3中实现二维码生成需要使用第三方库来处理生成二维码的逻辑。常用的库有 qrcode和 vue-qrcode。 一、基础用法实现 在Vue3中使用vue-qrcode库实现二维码生成的方…

记录一次云主机故障排查

云上某云主机&#xff0c;在安全组test-a中&#xff0c;同一安全组下还有另外两台主机。 从本地可以ping 通另外两台主机的公网地址。但是不能ping通这个主机的公网地址。 与是重启主机&#xff0c;发现问题依然存在。依然是不能ping 通&#xff0c;主机上部署的业务也不能访…

LabVIEW在齿轮箱故障诊断中的应用

LabVIEW在齿轮箱故障诊断中的应用 在现代机械工业中&#xff0c;齿轮箱作为重要的传动设备&#xff0c;其性能稳定性对整体机械系统的运行至关重要。故障的及时诊断和处理不仅保障了设备的稳定运行&#xff0c;还减少了维护成本。利用LabVIEW强大数据处理和仿真能力&#xff0…

新版IDEA中Git的使用(二)

说明&#xff1a;前面介绍了在新版IDEA中Git的基本操作&#xff0c;本文介绍关于分支合并、拉取等操作&#xff1b; 例如&#xff0c;现在有一个项目&#xff0c;分支如下&#xff1a; main&#xff1a;主分支&#xff1b; dev&#xff1a;开发分支&#xff1b; test&#x…

Springboot整合MVC进阶篇

一、概述 1.1SpringBoot整合SpringMVC配置 SpringBoot对SpringMVC的配置主要包括以下几个方面&#xff1a; 自动配置&#xff1a;SpringBoot会自动配置一个嵌入式的Servlet容器&#xff08;如Tomcat&#xff09;&#xff0c;并为我们提供默认的SpringMVC配置。这样我们无需手动…

【Java、Python】获取电脑当前网络IP进行位置获取(附源码)

我相信看到这篇博客的时候心里肯定是想解决自己的一个问题的&#xff0c;而这篇博客我就以简单快速的方式解决这些烦恼&#xff01; 一、获取当前IP 在Java中自带了一些自己的流对象来获取当前的IP地址&#xff0c;不多说我们直接上代码。 //获取当前网络ip地址 ipAddress Ine…
最新文章