单片机
返回首页

stm32f10x独立看门狗

2021-11-08 来源:eefocus

一、IWDG介绍

1.1、独立看门狗简介

STM21F1芯片内部含有两个看门狗外设,独立看门狗(IWDG)与窗口看门狗(WWDG)。

两个看门狗都可以用于检测并解决由软件错误导致的故障。

独立看门狗可以简单的理解为一个12位的递减计数器,当计数器从某个值递减到0时(如果看门狗已激活),那么系统会产生一次复位。

如果在计数器递减到0之前刷新了计数器值,那么系统就不会产生复位。

这个刷新计数器值得过程称为“喂狗”。

独立看门狗功能由VDD电压域供电,在停止模式和待机模式下仍能工作。


1.2、IWDG结构框图

LSI:内部低速时钟,频率约在30~60KHz之间   仅适用于时间精度较低的场合,即便在主时钟发生 故障时仍然保持工作状态。


8 位预分频寄存器 IWDG_PR :LSI 时钟并不是直接提供给计数器时钟,而是通过一个 8 位预分频寄存器 IWDG_PR 分频后输入给计数器时钟。操作 IWDG_PR 寄存器来设置分频因子。8位预处理器(寄存器):分频因子有2,4,8,16,32,64,128,256。分频后的计数器时钟为:CK_CNT= 40/ 4*2^PRE,PRE 为预分频系数(0-6),4*2^PRE 大小就是 4、8、16、32、64、128、256 值。每经过一个计数器时钟, 计数器就减 1。

12位递减计数器:独立看门狗的计数器是一个 12 位的递减计数器,计数最大值为 0XFFF,当递减到 0 时,会产生一个复位信号,让系统重新启动运行,如果在计数器减到 0

之前刷新了计数器值的话,就不会产生复位信号,这个刷新计数器值过程称 之为“喂狗”。


12位  重加载数值:重装载寄存器是一个 12 位的寄存器,里面装着要刷新到计数器的值,这个值的大小决定着独立看门狗的溢出时间。溢出时间 Tout = (4*2^pre) / 40 * rlr

(ms), pre 是预分频器系数(0-6),rlr 是重装载寄存器的值,公式内的 40 是 独立看门狗的时钟。 比如设置 pre=4,rlr=800,那么独立看门狗溢出时间是 1280ms,也就是说

如果在 1280ms 内没有进行喂狗,那么系统将进行重启,即程序重新开始运行

键寄存器(IWDG_KR)又称关键字寄存器或密钥寄存器(IWDG_KR)。此寄存器可以说 是 IWDG 的一个控制寄存器。往该寄存器写入三种值会有三种控制效果:

①写入 0X5555,由于 IWDG_PR 和 IWDG_RLR 寄存器具有写访问保护。若要 修改寄存器,必须首先对 IWDG_KR 寄存器写入代码 0x5555。若写入其他值将重 启写保护。

②写入 0XAAAA,把 IWDG_RLR 寄存器内值重装载到计数器中。


③写入 0XCCCC,启动 IWDG 功能。此方式属于软件启动,一旦开启独立看门 狗,它就关不掉,只有复位才能关掉IWDG的控制寄存器    

状态寄存器 IWDG_SR 只有位 0: PVU 和位 1: RVU 有效,这两位只能由硬件操作。RVU:看门狗计数器重装载值更新,硬件置 1 表示重装载值的更新正在进行中,更新完毕之后由硬件清 0。 PVU: 看门狗预分频值更新,硬件置 1 表示预分频值的更新正在进行中,当更新完成后,由硬件清 0。所以只有当 RVU/PVU 等于 0 的时候才可以更新重装载寄存器/预分频寄存器

二、IWDG配置

独立看门有自己的时钟LSI(内部低速时钟),不存在使能问题,但固件库还是提供LSI的使能函数

RCC_LSICmd(ENABLE); // 

while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==0){} // 复位LSE振荡器时钟

/**

  * @brief  Enables or disables the Internal Low Speed oscillator 振荡器(LSI).                                           使能或失能内部低速时钟

  * @note   LSI can not be disabled if the IWDG is running.                                                                        注意:当IWDG处于运行状态时,无法禁用LSI。

  * @param  NewState: new state of the LSI. This parameter can be: ENABLE or DISABLE.

  * @retval None

  */

void RCC_LSICmd(FunctionalState NewState)

{

  /* Check the parameters */

  assert_param(IS_FUNCTIONAL_STATE(NewState));

  *(__IO uint32_t *) CSR_LSION_BB = (uint32_t)NewState;

}


内部低速时钟开启为的别名地址


#define CSR_LSION_BB              (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4))


#define PERIPH_BB_BASE        ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */   位带区域内的外围基地地址


#define CSR_OFFSET                (RCC_OFFSET + 0x24)


/* ------------ RCC registers bit address in the alias region ----------- */    RCC在别名区域寄存器位地址

#define RCC_OFFSET                (RCC_BASE - PERIPH_BASE)


#define LSION_BitNumber           0x00


(1)IWDG相关库函数在stm32f10x_iwdg.c和stm32f10x_iwdg.h文件中 

  开启寄存器访问(给IWDG_KP寄存器写入0x5555)

IWDG_WriteAccesscmd(IWDG_WriteAccess_Enable); // 取消寄存器写保护

/**

  * @brief  Enables or disables write access to IWDG_PR and IWDG_RLR registers.                                  失能或使能独立看门狗的预分频寄存器和独立看门狗重装载寄存器的写访问

  * @param  IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers.          独立看门狗的预分频寄存器与独立看门狗重装载寄存器 写访问的新状态

  *   This parameter can be one of the following values:

  *     @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers         

  *     @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers

  * @retval None

  */

void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)

{

  /* Check the parameters */

  assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));           assert_param宏 拥有检测函数的参数

  IWDG->KR = IWDG_WriteAccess;                                                              IWDG的KR(健存寄存器) 的0~15位写入0x5555 (0101 0101 0101 0101)   表示允许操作IWDG_PR与IWDG_RLR  即取消寄存器写保护           

}


#define IWDG_WriteAccess_Enable     ((uint16_t)0x5555)                 //  取消写保护

#define IWDG_WriteAccess_Disable    ((uint16_t)0x0000)                 //  写保护

#define IS_IWDG_WRITE_ACCESS(ACCESS) (((ACCESS) == IWDG_WriteAccess_Enable) ||

                                      ((ACCESS) == IWDG_WriteAccess_Disable))


(2)设置IWDG预分频系数和重装载值

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler )       // 设置预分频的值

 

void IWDG_SetReload(uint16_t Reload);  // 设置重装载的值

 

Tout =(4*2^pre)/40*rlr

 

Tout独立看门狗的溢出时间,单位:ms。pre是预分频系数(0-6),rlr是重装载寄存器的值,

公式内的40是独立看门狗的时钟。

比如设置 pre=4,rlr=800,那么独立看门狗溢出时间是 1280ms,

只要在 1280ms 之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位   

看门狗的时钟不是准确的40Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位

/**

  * @brief  Sets IWDG Prescaler value.                                                    设置预分频寄存器的值

  * @param  IWDG_Prescaler: specifies the IWDG Prescaler value.

  *   This parameter can be one of the following values:                         4     8     16      32      64    128     256

  *     @arg IWDG_Prescaler_4: IWDG prescaler set to 4

  *     @arg IWDG_Prescaler_8: IWDG prescaler set to 8

  *     @arg IWDG_Prescaler_16: IWDG prescaler set to 16

  *     @arg IWDG_Prescaler_32: IWDG prescaler set to 32

  *     @arg IWDG_Prescaler_64: IWDG prescaler set to 64

  *     @arg IWDG_Prescaler_128: IWDG prescaler set to 128

  *     @arg IWDG_Prescaler_256: IWDG prescaler set to 256

  * @retval None

  */


void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)

{

  /* Check the parameters */

  assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));

  IWDG->PR = IWDG_Prescaler;                                                                预分频寄存器

}


/**

  * @brief  Sets IWDG Reload value.                                               独立看门狗重装载的值

  * @param  Reload: specifies the IWDG Reload value.                 设置独立看门狗重装载的值

  *   This parameter must be a number between 0 and 0x0FFF.     参数的取值范围0 ~ 0x0FFF

  * @retval None

  */

void IWDG_SetReload(uint16_t Reload)

{

  /* Check the parameters */

  assert_param(IS_IWDG_RELOAD(Reload));

  IWDG->RLR = Reload;

}


(3)重载计数器值(喂狗)给IWDG_KR寄存器写入0xAAAA

IWDG_ReloadCounter();

/**

  * @brief  Reloads IWDG counter with value defined in the reload register

  *   (write access to IWDG_PR and IWDG_RLR registers disabled).

  * @param  None

  * @retval None

  */

void IWDG_ReloadCounter(void)

{

  IWDG->KR = KR_KEY_Reload;

}


/* KR register bit mask */

#define KR_KEY_Reload    ((uint16_t)0xAAAA)       

#define KR_KEY_Enable    ((uint16_t)0xCCCC)


(4)开启IWDG(给IWDG_KR寄存器写入0xCCCC)

IWDG_Enable();

/**

  * @brief  Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled).

  * @param  None

  * @retval None

  */

void IWDG_Enable(void)

{

  IWDG->KR = KR_KEY_Enable;

}


四、编写独立看门狗

通过 KEY_UP 按键进行喂狗,喂狗的时候 DS1 点亮, 同时串口输出“喂狗”提示信息,超过喂狗时间系统重启 DS1 熄灭,同时串口输 出“复位系统”提示信息,同时使用 DS0 指示灯闪烁表示系统运行编写看门狗例子1

#include 'iwdg.h'

 

/*******************************************************************************

* 函 数 名         : IWDG_Init

* 函数功能    : IWDG初始化

* 输    入         : pre:预分频系数(0-6)

rlr:重装载值(12位范围0xfff)

独立看门狗复位时间计算公式:t=(4*2^pre*rlr)/40

* 输    出         : 无

*******************************************************************************/

void IWDG_Init(u8 pre,u16 rlr)

{

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //取消寄存器写保护

IWDG_SetPrescaler(pre);//设置预分频系数 0-6

IWDG_SetReload(rlr);//设置重装载值

IWDG_ReloadCounter();  //重装载初值

IWDG_Enable(); //打开独立看门狗

}

 

/*******************************************************************************

* 函 数 名         : IWDG_FeedDog

* 函数功能    : 喂狗

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void IWDG_FeedDog(void)  //喂狗

{

IWDG_ReloadCounter();  //重装载初值

}

 

头文件


#ifndef _iwdg_H

#define _iwdg_H

 

#include 'system.h'

void IWDG_Init(u8 pre,u16 rlr);

void IWDG_FeedDog(void);  //喂狗

 

#endif

 

主函数


#include 'system.h'

#include 'SysTick.h'

#include 'led.h'

#include 'usart.h'

#include 'key.h'

#include 'iwdg.h'

 

 

/*******************************************************************************

* 函 数 名         : main

* 函数功能    : 主函数

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

int main()

{

u8 i=0; 

SysTick_Init(72);  // 9M

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组

LED_Init();

USART1_Init(115200); // 串口通信波特率

KEY_Init();

IWDG_Init(4,800); //只要在1280ms内进行喂狗就不会复位系统

LED2=1;

printf('复位系统rn');

while(1)

{

if(KEY_Scan(0)==KEY_UP_PRESS)

{

IWDG_FeedDog();//喂狗

LED2=0;

printf('喂狗rn');

}

i++;

if(i%20==0)

{

LED1=!LED1;

}

delay_ms(10); // 200ms

}

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 如何构建一个触摸传感器电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章