一,独立看门狗

二,独立看门狗的时钟源

独立看门狗拥有自己的时钟源,不依赖PLL时钟输出的分频信号,能够独立运行,这样子的好处就是PLL假如受到干扰,

导致运行异常,独立的看门狗还能正常地进行工作,如果没有正常的喂狗动作,就复位CPU。

三、程序设计

1.     添加复位检测代码,有助于观察当前工作的可靠性

   /* Check if the system has resumed from IWDG reset,检查当前复位是否有独立看门狗导致 */if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET){/* IWDGRST flag set */printf("iwdt reset cpu\r\n");/* Clear reset flags */RCC_ClearFlag();}else{/* IWDGRST flag is not set */printf("normal reset cpu\r\n");}

2.

/* Enable write access to IWDG_PR and IWDG_RLR registers,独立看门狗是受到保护的,现在进行解锁动作 */IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);/* IWDG counter clock: LSI/256 ,设置看门狗的时钟 = 32KHz / 256 =125Hz */IWDG_SetPrescaler(IWDG_Prescaler_256);/* 设置看门狗的超时时间,也就是设置它的计数值当前看门狗的时钟为125Hz,然后设置超时时间为1秒,那么重载值为125当前看门狗的时钟为125Hz,然后设置超时时间为2秒,那么重载值为250*/   IWDG_SetReload(125);/* Reload IWDG counter,重载独立看门狗的计数值,说白了就是喂狗 */IWDG_ReloadCounter();/* Enable IWDG (the LSI oscillator will be enabled by hardware),使能独立看门狗 */IWDG_Enable();

3.     喂狗技巧

1.在裸机代码实现喂狗,放在定时器里面,因为定时器与看门狗是使用不同的时钟源,允许这么做!

2.     如果有实时的操作系统的加持,可以在任务里面添加喂狗动作,如果操作系统崩溃了,能够检测到软件的错误,触发CPU的复位。

在定时器中断服务函数当中,添加喂狗动作!

#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stdio.h"static GPIO_InitTypeDef      GPIO_InitStructure;
static USART_InitTypeDef     USART_InitStructure;
static NVIC_InitTypeDef     NVIC_InitStructure;           void delay_us(uint32_t nus)
{        uint32_t temp;             SysTick->LOAD =SystemCoreClock/8/1000000*nus;     //时间加载               SysTick->VAL  =0x00;                            //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;         //使能滴答定时器开始倒数      do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));            //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;         //关闭计数器SysTick->VAL =0X00;                               //清空计数器
}void delay_ms(uint16_t nms)
{                     uint32_t temp;           SysTick->LOAD=SystemCoreClock/8/1000*nms;        //时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;                               //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        //能滴答定时器开始倒数 do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));            //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        //关闭计数器SysTick->VAL =0X00;                               //清空计数器
} void LED_Init(void)
{         //使能GPIOE,GPIOF时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF, ENABLE);            //GPIOF9,F10初始化设置 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9 | GPIO_Pin_10;        //LED0和LED1对应IO口GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;                    //普通输出模式,GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                    //推挽输出,驱动LED需要电流驱动GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                //100MHzGPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;                    //上拉GPIO_Init(GPIOF, &GPIO_InitStructure);                            //初始化GPIOF,把配置的数据写入寄存器                        //GPIOE13,PE14初始化设置 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13 | GPIO_Pin_14;        //LED2和LED3对应IO口GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;                    //普通输出模式GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                    //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                //100MHzGPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;                    //上拉GPIO_Init(GPIOE, &GPIO_InitStructure);                            //初始化GPIOE,把配置的数据写入寄存器
GPIO_SetBits(GPIOF,GPIO_Pin_9  | GPIO_Pin_10);                    //GPIOF9,PF10设置高,灯灭GPIO_SetBits(GPIOE,GPIO_Pin_13 | GPIO_Pin_14);
}void USART1_Init(uint32_t baud)
{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);                             //使能GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);                            //使能USART1时钟//串口1对应引脚复用映射GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);                         //GPIOA9复用为USART1GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);                         //GPIOA10复用为USART1//USART1端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;                         //GPIOA9与GPIOA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                                    //复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                //速度50MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                                     //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                                     //上拉GPIO_Init(GPIOA,&GPIO_InitStructure);                                             //初始化PA9,PA10//USART1 初始化设置USART_InitStructure.USART_BaudRate = baud;                                        //波特率设置USART_InitStructure.USART_WordLength = USART_WordLength_8b;                        //字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;                            //一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;                                //无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    //无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                    //收发模式USART_Init(USART1, &USART_InitStructure);                                         //初始化串口1
    USART_Cmd(USART1, ENABLE);                                                      //使能串口1
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                                    //开启相关中断//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                                //串口1中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;                            //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;                                //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                    //IRQ通道使能NVIC_Init(&NVIC_InitStructure);                                                    //根据指定的参数初始化VIC寄存器
}//重定义fputc
int fputc(int ch,FILE *f)
{USART_SendData(USART1,ch);while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);return ch;
}void usart1_send_bytes(uint8_t *pbuf,uint32_t len)
{while(len--){USART_SendData(USART1,*pbuf++);while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);}
}void usart1_send_str(char *pbuf)
{while(pbuf && *pbuf){USART_SendData(USART1,*pbuf++);while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);}
}int main(void)
{ LED_Init();        //系统定时器初始化,时钟源来自HCLK,且进行8分频,//系统定时器时钟频率=168MHz/8=21MHz
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //设置中断优先级分组2
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//串口1,波特率115200bps,开启接收中断USART1_Init(115200);/* Check if the system has resumed from IWDG reset,检查当前复位是否有独立看门狗导致 */if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET){/* IWDGRST flag set */printf("iwdt reset cpu\r\n");/* Clear reset flags */RCC_ClearFlag();}else{/* IWDGRST flag is not set */printf("normal reset cpu\r\n");}/* Enable write access to IWDG_PR and IWDG_RLR registers,独立看门狗是受到保护的,现在进行解锁动作 */IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);/* IWDG counter clock: LSI/256 ,设置看门狗的时钟 = 32KHz / 256 =125Hz */IWDG_SetPrescaler(IWDG_Prescaler_256);/* 设置看门狗的超时时间,也就是设置它的计数值当前看门狗的时钟为125Hz,然后设置超时时间为1秒,那么重载值为125当前看门狗的时钟为125Hz,然后设置超时时间为2秒,那么重载值为250*/   IWDG_SetReload(125);/* Reload IWDG counter,重载独立看门狗的计数值,说白了就是喂狗 */IWDG_ReloadCounter();/* Enable IWDG (the LSI oscillator will be enabled by hardware),使能独立看门狗 */IWDG_Enable();while(1){//重载计数值,就是喂狗,就是不让计数值变为0
        IWDG_ReloadCounter();  }
}void USART1_IRQHandler(void)                                //串口1中断服务程序
{uint8_t d;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)      //接收中断
    {//接收数据d = USART_ReceiveData(USART1);                        //发送数据usart1_send_bytes(&d,1);} } 

---恢复内容结束---

转载于:https://www.cnblogs.com/xiangtingshen/p/10963552.html

独立看门狗 IWDG相关推荐

  1. STM32F103五分钟入门系列(十三)独立看门狗IWDG

    参考:STM32F103五分钟入门系列(十三)独立看门狗IWDG 作者:自信且爱笑' 发布时间:2021-07-31 19:50:28 网址:https://blog.csdn.net/Curnane ...

  2. STM32F1笔记(六)独立看门狗IWDG

    STM32F1内置了两个看门狗,独立看门狗IWDG和窗口看门狗WWDG,可以用来检测和解决由软件错误引起的故障. IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精 ...

  3. stm32专题三十四:独立看门狗 IWDG

    独立看门狗简介 IWDG结构框图 (1)独立看门狗时钟 独立看门狗的时钟由独立的 RC 振荡器 LSI 提供, 即使主时钟发生故障它仍然有效,非常独立. LSI 的频率一般在 30~60KHZ 之间, ...

  4. 独立看门狗IWDG详细解析

    目录 独立看门狗IWDG详细解析 为什么要有看门狗? 看门狗的定时原理 寄存器功能简介 看门狗定时器计数原理 看门狗相关寄存器 KR寄存器 PR寄存器 RLR寄存器 SR寄存器 看门狗相关基础知识 什 ...

  5. STM32—独立看门狗(IWDG)

    STM32-独立看门狗(IWDG) 独立看门狗(IWDG) STM32-独立看门狗(IWDG) 独立看门狗(IWDG) IWDG 简介 IWDG 功能框图剖析 独立看门狗时钟 计数器 重装载寄存器 键 ...

  6. cubeIDE开发, stm32独立看门狗IWDG的CubeMX配置及HAL库底层实现分析

    一.STM32 的IWDG简介 2.1 看门狗原理 看门狗本质上就是一种计数器,和我们现实生活中一炷香现象.沙漏现象等是同理的,计数器一般有两种做法,一种是递增,超过固定阀值报警:一种是递减,通常值降 ...

  7. STM32 - 独立看门狗IWDG - 使用注意事项+代码

    一.包含头文件 #include "stm32f10x_iwdg.h" 二.设置 独立看门狗 的超时时间 1.配置代码 /** 设置 IWDG 的超时时间* Tout(ms) = ...

  8. [STM32 ]内部独立看门狗IWDG

    看门狗大家应该都不陌生,STM32内部带有独立看门狗和窗口看门狗两种:其中独立看门狗依赖于内部的晶振LSI进行工作,窗口看门狗依赖于系统时钟工作: 看门狗的作用,防止程序跑飞无法实现自复位而存在:如果 ...

  9. 从零实现 独立看门狗IWDG STM32的待机与唤醒,在待机过程中如何喂狗

    欢迎大家留言交流~ 前言: 最近在学习原子的阿波罗,进行到待机实验,实验目的是摁下KEY_UP的时候就可以让MCU从待机模式唤醒了.而KEY1在按下的时候进入休眠.(验证过程比较繁琐,只看结论的小伙伴 ...

最新文章

  1. BigDecimal 转换为int 或者其他类型
  2. 【FPGA】SRIO IP核系统总览以及端口介绍(一)(User Interfaces 之 I/O Port)
  3. Vue-路由模式 hash 和 history
  4. WRF,WPS,WRF-Chem安装及编译步骤及bug总结(2)
  5. matlab 信号去直流,基于FIR滤波的ADC采样信号中直流信号的消除方法与流程
  6. 机器学习实战-逻辑回归-19
  7. JQuery源码解析(一)
  8. 走进rxjs的世界 - 万物皆流 - Everything is a stream
  9. 2021 年 7 月程序员工资统计,最赚钱的岗位出炉。。
  10. 屏幕居中(DIV/CSS) 的几种方法
  11. Python脚本编译为可跨平台、跨架构执行的字节码文件pyc方法
  12. 综合能源系统及其应用
  13. 数字转为汉语中人民币的大写
  14. 迪杰斯特拉算法(求最短路径)
  15. python 离线安装setuptools_离线安装setuptools
  16. pandas 取某一列数据的几种形式比较
  17. ESD5401N-2/TR 瞬态电压抑制器 封装DFN1006-2L WILLSEM
  18. uni-app小程序结合腾讯地图获取定位以及地图选址
  19. uniapp 中如何使用echart_uni-app中使用Echarts绘画图表
  20. [html] 写一个鼠标跟随的特效

热门文章

  1. 【linux工具】Tmux简明教程
  2. 登入学生账号的c语言编码,C语言学生账号信息管理系统.pdf
  3. Android 四大组件 Service
  4. JS 跑马灯效果实现(很好用)
  5. Altium Designer导入3D模型出现:cannot load 3D model from file警告
  6. npoi css,NPOI 扩展:NPOI.CSS_html/css_WEB-ITnose
  7. Python分析csv文件及可视化绘图
  8. [Go实战]gin框架+realize实现边写代码边编译,热更新,方便边改边看效果
  9. 做好HR必读的人力资源书单推荐
  10. Hyperledger fabric的项目实战---江苏省农牧厅渔业管理系统业务分析