独立看门狗 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 ...
随机推荐
- Merkle树
在分布式系统.P2P应用中或者是区块链中,会经常使用一种数据结构Merkle tree(默克尔树),这里我们将详细讨论一下这个常用数据结构. Merkle tree Merkle树看起来非常像二叉树, ...
- 【转】Visual Studio Code必备插件
先ctrl+shift+p,弹出命令面板-选中Extensions:Install Extensions 或者直接点击左侧栏这个扩展按钮(Ctrl+Shift+X) 然后左侧栏就会显示出很多插件,如图 ...
- 手机如何修改host文件
常常在想本地开发的时候使用pc端测试移动端,由于有安全域名限制,因此在本地修改了机器的host.将域名映射到本地局域网.这个做法是很正常的也很常见.但是现在新的需求是我需要在手机上也能够正常测试啊!怎 ...
- Asp.Net Core 轻松学系列-3项目目录和文件作用介绍
目录 前言 结语 前言 上一章介绍了 Asp.Net Core 的前世今生,并创建了一个控制台项目编译并运行成功,本章的内容介绍 .NETCore 的各种常用命令.Asp.Net Core M ...
- Django-2.0 汉化
1.语言 LANGUAGE_CODE = 'zh-hans' 2.时区 TIME_ZONE = 'Asia/Shanghai' 3.字段名汉化 models.CharFielf(verbose_nam ...
- 十六进制转换十进制(JAVA版)
解题思路路大概为:现将十六进制数转换为二进制数,再讲二进制数转换为八进制数.在进行十六进制转换为八进制时可以利用JAVA中的‘&’运算符号,一个十六进制数可以表示为四个二进制数,利用‘& ...
- 恺撒密码 I
恺撒密码 I ...
- WIN10升级失败,故障代码 0X8007042B-0X4000D 解决
个人博客链接:WIN10升级失败,故障代码 0X8007042B-0X4000D 解决
- 从c到c++<一>
逻辑型也称布尔型,其取值为true(逻辑真)和false(逻辑假),存储字节数在不同编译系统中可能有所不同,VC++中为1个字节. 声明方式: bool result; result=true; 可以 ...
- Java&Selenium智能等待方法封装
Java&Selenium智能等待方法封装 ExpectedConditions方法还有很多,自然也可以继续扩展很多 package util; import org.openqa.selen ...