独立看门狗 IWDG
一,独立看门狗
二,独立看门狗的时钟源
独立看门狗拥有自己的时钟源,不依赖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();
- /* 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//*nus; //时间加载
- SysTick->VAL =0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(<<))); //等待时间到达
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
- SysTick->VAL =0X00; //清空计数器
- }
- void delay_ms(uint16_t nms)
- {
- uint32_t temp;
- SysTick->LOAD=SystemCoreClock//*nms; //时间加载(SysTick->LOAD为24bit)
- SysTick->VAL =0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //能滴答定时器开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(<<))); //等待时间到达
- 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; //100MHz
- GPIO_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; //100MHz
- GPIO_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复用为USART1
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
- //USART1端口配置
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
- GPIO_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
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =; //子优先级3
- NVIC_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();
- /* 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();
- /* Reload IWDG counter,重载独立看门狗的计数值,说白了就是喂狗 */
- IWDG_ReloadCounter();
- /* Enable IWDG (the LSI oscillator will be enabled by hardware),使能独立看门狗 */
- IWDG_Enable();
- while()
- {
- //重载计数值,就是喂狗,就是不让计数值变为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,);
- }
- }
---恢复内容结束---
独立看门狗 IWDG的更多相关文章
- stm32 独立看门狗 IWDG
独立看门狗IWDG 独立看门狗简单理解就是一个12位递减计数器,当计数器从某一个值递减到0时,系统就会产生一次复位 独立看门狗由专用低速时钟LSI驱动,其频率一般在30-60KHz之间,通常选择40K ...
- (stm32f103学习总结)—独立看门狗(IWDG)
一.IWDG介绍 1.1 IWDG简介 STM32F1芯片内部含有两个看门狗外设,一个是独立看门狗IWDG,另 一个是窗口看门狗WWDG.两个看门狗外设(独立和窗口)均可用于检测 并解决由软件错误导致 ...
- STM32之独立看门狗(IWDG)与窗口看门狗(WWDG)总结
一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...
- STM8L独立看门狗IWDG
简单扼要 void IWDG_Init(void)//初始化 { IWDG->KR = 0xcc;//启动IWDG IWDG->KR = 0x55;//解除PR及RLR的写保护 IWDG- ...
- stm32 独立看门狗学习
STM32F10xxx内置两个看门狗,提供了更高的安全性.时间的精确性和使用的灵活性.两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障. 独立看门狗(IWDG)由专用的低速 ...
- STM32之------独立看门狗(IWDG)和窗体看门狗(WWDG)
一 前沿废语: 之前有很风靡的游戏,名字叫<看门狗>.该游戏用了很新的引擎技术,打造出了一个辽阔庞大的世界,内容是玩家Aiden·Pearce(主角)是一名精通黑客技术的高手,当时 ...
- IWDG—独立看门狗
本章参考资料:<STM32F4XX 中文参考手册> IWDG 章节.学习本章时,配合<STM32F4XX 中文参考手册> IWDG 章节一起阅读,效果会更佳,特别是涉及到寄存器 ...
- 第34章 IWDG—独立看门狗—零死角玩转STM32-F429系列
第34章 IWDG—独立看门狗 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
- STM32独立看门狗(IWDG)
造成程序跑飞,只是程序的正常运行状态被打断而进入死循环,从而使单片机控制的系统无法正常工作.看门狗就是一种专门用于检测单片机程序运行状态的硬件结构. STM32内部自带了两个看门狗,独立看门狗(IWD ...
随机推荐
- redis 缓存对象、列表
在spring boot环境下有个StringRedisTemplate对象,默认已经为我们配置好了,只需要自动注入过来就能用,但是使用它只能在Redis中存放字符串.具体操作如下: @RunWith ...
- PHP运行机制和原理
以echo "Hello World";为例 经历五个步骤:1.扫描(scanning):先进行语法分析和词法分析,然后将index.php内容变成一个个语言片段(token ar ...
- Eclipse syntax coloring java xml 语法 样式
自定义java源文件的编码样式,包括关键词等等的样式和颜色等,可以一边调下面就能看到样式效果,这是我自己一个个设置好的如图 自定义xml文件编辑器的样式格式,其实我装了sublime 但是 eclip ...
- 恺撒密码 I
恺撒密码 I ...
- vue-filters(过滤器)
局部过滤器: <html> <head> <title>vue</title> <meta charset="utf-8"&g ...
- ARC模式下获取retainCount的方法
_objc_rootRetainCount(obj)可以获取obj的retainCount,不过不清楚是不是私有api,因此建议调试时使用.
- C++ 项目和资源导引
值得学习的C语言开源项目 注意:本文转载自:https://blog.csdn.net/a110658684/article/details/78862348 - 1. Webbench Webben ...
- linux文件系统初学
Linux磁盘分区和目录 Linux发行版之间的差别很小,差别主要表现在系统管理的特色工具以及软件包管理方式的不同. Windows的文件结构是多个并列的树状结构,最顶部是不同的磁盘(分区),如C,D ...
- vue组件间的传值方式及方法调用汇总
1.传值 a.父组件传子组件 方法一: 父页面: <myReportContent v-if="contentState==1" :paramsProps='paramsPr ...
- Spark学习笔记2——RDD(上)
目录 Spark学习笔记2--RDD(上) RDD是什么? 例子 创建 RDD 并行化方式 读取外部数据集方式 RDD 操作 转化操作 行动操作 惰性求值 Spark学习笔记2--RDD(上) 笔记摘 ...