STM32
直播中

djelje

9年用户 1092经验值
擅长:光电显示
私信 关注
[问答]

有关窗口看门狗WWDG的相关知识简析

窗口看门狗WWDG的原理是什么?
窗口看门狗WWDG有哪些功能?
如何去使用窗口看门狗WWDG?

回帖(1)

文妮

2021-9-23 11:33:41
  一、WWDG原理
  经过前面的学习我们知道IWDG的工作原理就是一个递减计数器在LSI时钟的驱动下不断的往下递减计数,当减到0x000之前如果没有刷新递减计数器的值——即喂狗的话,就会产生CPU复位。窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值0X40 时还不喂狗的话,产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。
  窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。
  IWDG 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时 间精度要求较低的场合。
  
  
  IWDG与WWDG区别
  RLR 是重装载寄存器,用来设置独立看门狗的计数器的值。TR 是窗口看门狗的计数器的值,由用户独立设置,WR 是窗口看门狗的上窗口值,由用户独立设置。
  二、WWDG功能框图
  
  1、窗口看门狗时钟来自PCLK1,PCLK1 最大是42M,由RCC 时钟控制器开启。
  2、计数器时钟由CK 计时器时钟经过预分频器分频得到,分频系数由配置寄存器CFR 的位8:7 WDGTB[1:0]配置,可以是[0,1,2,3],其中CK 计时器时钟=PCLK1/4096,除以4096是手册规定的,没有为什么。所以计数器的时钟CNT_CK=PCLK1/4096/(2^WDGTB),
  这就可以算出计数器减一个数的时间T= 1/CNT_CK = Tpclk1 * 4096 * (2^WDGTB)。
  3、窗口看门狗的计数器是一个递减计数器,共有7 位,其值存在控制寄存器CR 的位6:0,即T[6:0],当7 个位全部为1 时是0X7F,这个是最大值,当递减到T6 位变成0 时,即从0X40 变为0X3F 时候,会产生看门狗复位。这个值0X40 是看门狗能够递减到的最小值,所以计数器的值只能是:0X40~0X7F 之间,实际上用来计数的是T[5:0]。当递减计数器递减到0X40 的时候,还不会马上产生复位,如果使能了提前唤醒中断:CFR 位9 EWI 置1,则产生提前唤醒中断,如果真进入了这个中断的话,就说明程序肯定是出问题了,那么在中断服务程序里面我们就需要做最重要的工作,比如保存重要数据,或者报警等,这个中断我们也叫它死前中断。
  
  4、窗口看门狗必须在计数器的值在一个范围内才可以喂狗,其中下窗口的值是固定的0X40,上窗口的值可以改变,具体的由配置寄存器CFR 的位6:0 W[6:0]设置。其值必须大于0X40,如果小于或者等于0X40 就是失去了窗口的价值,而且也不能大于计数器的值,所以必须得小于0X7F。那窗口值具体要设置成多大?这个得根据我们需要监控的程序的运行时间来决定。如果我们要监控的程序段A 运行的时间为Ta,当执行完这段程序之后就要进行喂狗,如果在窗口时间内没有喂狗的话,那程序就肯定是出问题了。一般计数器的值TR 设置成最大0X7F,窗口值为WR,计数器减一个数的时间为T,那么时间:(TR-WR)*T 应该稍微大于Ta 即可,这样就能做到刚执行完程序段A 之后喂狗,起到监控的作用,这样也就可以算出WR的值是多少。
  
  位 31:10 保留,必须保持复位值。
  位 9 EWI:提前唤醒中断 (Early wakeup interrupt)置 1 后,只要计数器值达到 0x40 就会产生中断。此中断只有在复位后才由硬件清零。
  位 8:7 WDGTB[1:0]:定时器时基 (Timer base)
  可按如下方式修改预分频器的时基:
  00:CK 计数器时钟 (PCLK1 div 4096) 分频器 1
  01:CK 计数器时钟 (PCLK1 div 4096) 分频器 2
  10:CK 计数器时钟 (PCLK1 div 4096) 分频器 4
  11:CK 计数器时钟 (PCLK1 div 4096) 分频器 8
  位 6:0 W[6:0]:7 位窗口值 (7-bit window value)
  这些位包含用于与递减计数器进行比较的窗口值。
  三、WWDG的用法
  《textarea readonly=“readonly” name=“code” class=“c++”》 //保存WWDG计数器的设置值,默认为最大,窗口值的上限值。
  uint8_t WWDG_CNT=0X7F;
  //初始化窗口看门狗
  //tr :T[6:0],计数器值
  //wr :W[6:0],窗口值
  //fprer:分频系数(WDGTB),仅最低2位有效
  //Fwwdg=PCLK1/(4096*2^fprer)。 一般PCLK1=42Mhz
  void WWDG_Init(uint8_t tr,uint8_t wr,u32 fprer)
  {
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //使能窗口看门狗时钟
  //0x7F
  WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
  WWDG_SetPrescaler(fprer); //设置分频值
  WWDG_SetWindowValue(wr); //设置窗口值
  WWDG_SetCounter(WWDG_CNT); //设置计数值
  WWDG_Enable(WWDG_CNT); //开启看门狗
  NVIC_InitStructure.NVIC_IRQChannel=WWDG_IRQn; //窗口看门狗中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02; //抢占优先级为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级为3
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能窗口看门狗
  NVIC_Init(&NVIC_InitStructure);
  WWDG_ClearFlag(); //清除提前唤醒中断标志位
  WWDG_EnableIT(); //开启提前唤醒中断
  }《/textarea》
  int main(void)
  {
  //系统时钟的时钟源=168MHz/8=21MHz
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
  LED_Init();
  usart1_init(115200);
  //所有灯亮
  PFout(9)=0;
  PFout(10)=0;
  PEout(13)=0;
  PEout(14)=0;
  delay_ms(500);
  //所有灯灭
  PFout(9)=1;
  PFout(10)=1;
  PEout(13)=1;
  PEout(14)=1;
  //获取当前复位状态是否为窗口看门狗引起的
  if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET)
  {
  printf(“This is wwdg reset cpu.。。rn”);
  //清除标志
  RCC_ClearFlag();
  }
  else
  {
  printf(“This is not wwdg reset cpu.。。rn”);
  }
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2
  //窗口看门狗时钟=42MHz/4096/8=1282Hz
  //计数值为0x7F
  //窗口上限值为0x4F
  WWDG_Init(0x7F,0X4F,WWDG_Prescaler_8); //计数器值为7f,窗口寄存器为5f,分频数为8
  while(1)
  {
  //在循环体里面一直重设窗口看门狗值,系统会复位
  #if 0
  WWDG_SetCounter(WWDG_CNT); //重设窗口看门狗值
  WWDG_ClearFlag(); //清除提前唤醒中断标志位
  #endif
  }
  }
  //窗口看门狗中断服务程序
  void WWDG_IRQHandler(void)
  {
  //若不进行窗口看门狗喂狗操作,则进行复位操作
  #if 1
  WWDG_SetCounter(WWDG_CNT); //重设窗口看门狗值
  WWDG_ClearFlag(); //清除提前唤醒中断标志位
  #endif
  GPIO_ToggleBits(GPIOE,GPIO_Pin_14);
  }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分