查看: 519|回复: 0

CH32V103应用教程——WWDG

[复制链接]

41

主题

168

帖子

3165

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3165
发表于 2021-11-27 19:58:57 | 显示全部楼层 |阅读模式
本章教程通过串口调试助手打印显示程序运行状态,具体现象如下:
  • 若计数器值在上窗口值和下窗口值0X40之间的时候,进行喂狗操作,计数器重新计数,程序正常运行,串口打印显示:The program runs normally;
  • 若程序在快要减到0X3F时候通过中断函数进行喂狗操作,则串口打印显示:Execute interrupt function The program runs normally;
  • 若程序没有在窗口时间内进行喂狗操作,则程序会不停进行复位。


1、WWDG简介及相关函数介绍
窗口看门狗(WWDG)通常用来监测系统运行的软件故障,例如外部干扰、不可预见的逻辑错误等情况。其需要在一个特定的窗口时间(有上下限)内进行计数器刷新(喂狗),否则早于或者晚于这个窗口时间看门狗电路都会产生系统复位。

CH32V103的窗口看门狗具有可编程的7位自减型计数器;具有双条件复位,当计数器值小于0X40,或者计数器值在窗口时间外被重装载;具有唤醒提前通知功能(EWI),用于及时喂狗动作防止系统复位。

CH32V103的窗口看门狗运行基于一个可编程的7 位的自减型计数器,其挂载在 APB1 总线下,计数时基 WWDG_CLK 来源(PCLK1/4096)时钟的分频,分频系数在配置寄存器 WWDG_CFGR 中的 WDGTB[1:0]域设置。递减计数器处于自由运行状态,无论看门狗功能是否开启,计数器一直循环递减计数。 关于CH32V103窗口看门狗具体信息,可参考CH32V103应用手册。

本章教程通过调用窗口看门狗库函数中相关函数进行程序编写,关于库函数相关介绍如下:
  1. void WWDG_DeInit(void);
  2. void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
  3. void WWDG_SetWindowValue(uint8_t WindowValue);
  4. void WWDG_EnableIT(void);
  5. void WWDG_SetCounter(uint8_t Counter);
  6. void WWDG_Enable(uint8_t Counter);
  7. FlagStatus WWDG_GetFlagStatus(void);
  8. void WWDG_ClearFlag(void);
复制代码
1.1、void WWDG_DeInit(void)
功  能:将WWDG外围寄存器初始化为其默认重置值
输  入:无

1.2、void WWDG_SetPrescaler(uint32_t WWDG_Prescaler)
功  能:设置WWDG预分频器
输  入:WWDG_预分频器:指定WWDG预分频器。

1.3、void WWDG_SetWindowValue(uint8_t WindowValue)
功  能:设置WWDG窗口值。
输  入:WindowValue:指定要与downcounter比较的窗口值,该值必须小于0x80

1.4、void WWDG_EnableIT(void)
功  能:启用WWDG早期唤醒中断(EWI)
输  入:无

1.5、void WWDG_SetCounter(uint8_t Counter)
功  能:设置WWDG计数器值
输  入:Counter:指定看门狗计数器值,该值必须是介于0x40和0x7F之间的数字。

1.6、void WWDG_Enable(uint8_t Counter)
功  能:启用WWDG并加载计数器值
输  入:Counter:指定看门狗计数器值,该值必须是介于0x40和0x7F之间的数字。

1.7、FlagStatus WWDG_GetFlagStatus(void)
功  能:检查是否设置了早期唤醒中断标志
输  入:无

1.8、void WWDG_ClearFlag(void)
功  能:清除提前唤醒中断标志
输  入:无

2、硬件设计
窗口看门狗属于CH32V103内部资源,无需进行任何硬件设计,只需通过串口监视器打印显示观察其运行状态即可。

3、软件设计
本教程中窗口看门狗主要通过在窗口时间内喂狗或在中断服务函数内喂狗保证系统程序正常运行,程序如下:
  • 1.窗口看门狗配置函数

  1. /*******************************************************************************
  2. * 函数名  : WWDG_Config
  3. * 描述    : 初始化窗口看门狗.
  4. * 输入    : tr:递减计数器值;wr:上窗口值;prv:分频系数
  5. * 返回    : None
  6. *******************************************************************************/
  7. void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
  8. {
  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //WWDG时钟使能
  10.     WWDG_SetCounter( tr );      //设置WWDG递减计数器值
  11.     WWDG_SetWindowValue( wr );  //设置WWDG上窗口值
  12.     WWDG_SetPrescaler( prv );   //设置WWDG预分频器值
  13.     WWDG_Enable(WWDG_CNT);      //设置计数器初始值并使能看门狗
  14.     WWDG_ClearFlag();           //清除提前唤醒中断标志
  15.     WWDG_NVIC_Config();         //初始化窗口看门狗NVIC
  16.     WWDG_EnableIT();            //开启窗口看门狗中断
  17. }
复制代码
  • 2.配置窗口看门狗中断

  1. /*******************************************************************************
  2. * 函数名  : WWDG_NVIC_Config
  3. * 描述    : 初始化看门狗NVIC,配置优先级.
  4. * 输入    : None
  5. * 返回    : None
  6. *******************************************************************************/
  7. void WWDG_NVIC_Config(void)
  8. {
  9.   NVIC_InitTypeDef NVIC_InitStructure;
  10.   NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;           //WWDG中断
  11.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
  12.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //响应优先级 0
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //使能通道1中断
  14.   NVIC_Init(&NVIC_InitStructure);                           //NVIC初始化
  15. }
复制代码
  • 3.喂狗函数

  1. //喂狗
  2. void WWDG_Feed(void)
  3. {
  4.     WWDG_SetCounter( WWDG_CNT );//喂狗,刷新递减计数器的值,设置成最大WWDG_CNT=0X7F
  5. }
复制代码
  • 4.中断函数

  1. //WWDG中断服务函数
  2. void WWDG_IRQHandler(void)
  3. {
  4.     WWDG_Feed();
  5.     WWDG_ClearFlag();           //清除提前唤醒中断标志位
  6.     printf("Execute interrupt function\r\n");
  7. }
复制代码
  • 5.所有程序

  1. #include <CH32V103.h>
  2. #include "HardwareSerial.h"

  3. #define  WWDG_CNT  0x7f

  4. /*******************************************************************************
  5. * 函数名  : WWDG_NVIC_Config
  6. * 描述    : 初始化看门狗NVIC,配置优先级.
  7. * 输入    : None
  8. * 返回    : None
  9. *******************************************************************************/
  10. void WWDG_NVIC_Config(void)
  11. {
  12.   NVIC_InitTypeDef NVIC_InitStructure;
  13.   NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;           //WWDG中断
  14.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0
  15.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //响应优先级 0
  16.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //使能通道1中断
  17.   NVIC_Init(&NVIC_InitStructure);                           //NVIC初始化
  18. }

  19. /*******************************************************************************
  20. * 函数名  : WWDG_Config
  21. * 描述    : 初始化窗口看门狗.
  22. * 输入    : tr:递减计数器值;wr:上窗口值;prv:分频系数
  23. * 返回    : None
  24. *******************************************************************************/
  25. void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
  26. {
  27.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //WWDG时钟使能
  28.     WWDG_SetCounter( tr );      //设置WWDG递减计数器值
  29.     WWDG_SetWindowValue( wr );  //设置WWDG上窗口值
  30.     WWDG_SetPrescaler( prv );   //设置WWDG预分频器值
  31.     WWDG_Enable(WWDG_CNT);      //设置计数器初始值并使能看门狗
  32.     WWDG_ClearFlag();           //清除提前唤醒中断标志
  33.     WWDG_NVIC_Config();         //初始化窗口看门狗NVIC
  34.     WWDG_EnableIT();            //开启窗口看门狗中断
  35. }

  36. /*******************************************************************************
  37. * 函数名  : WWDG_Feed
  38. * 描述    : 喂狗.
  39. * 输入    : None
  40. * 返回    : None
  41. *******************************************************************************/
  42. void WWDG_Feed(void)
  43. {
  44.     WWDG_SetCounter( WWDG_CNT );//喂狗,刷新递减计数器的值,设置成最大WWDG_CNT=0X7F
  45. }

  46. /*******************************************************************************
  47. * 函数名  : WWDG_IRQHandler
  48. * 描述    : WWDG中断服务函数.
  49. * 输入    : None
  50. * 返回    : None
  51. *******************************************************************************/
  52. extern "C"{
  53. void WWDG_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  54. void WWDG_IRQHandler(void)
  55. {
  56.   WWDG_Feed();
  57.   WWDG_ClearFlag();           //清除提前唤醒中断标志位
  58.   Serial1.println("Execute interrupt function");
  59. }
  60. }

  61. int main(void)
  62. {
  63.   uint8_t wwdg_tr,wwdg_wr;
  64.   CH32_Init();
  65.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  66.   Serial1.begin(115200);
  67.   Serial1.println("SystemClk:"+String(SystemCoreClock));
  68.   Serial1.println("WWDG Test");
  69.   
  70.   WWDG_Config(0x7f,0x5f,WWDG_Prescaler_8);      /* 36M/8/4096 */
  71.   wwdg_wr=WWDG->CFGR & 0x7F;
  72.   
  73.   while(1){
  74.     delay(40);//延时时间修改53ms以上,就会进入中断
  75.     Serial1.println("The program runs normally");
  76.     wwdg_tr=WWDG->CTLR & 0x7F;
  77.     if(wwdg_tr<wwdg_wr)
  78.     {
  79.       WWDG_Feed();
  80.     }
  81.   }
  82.   return 1;
  83. }

复制代码
4.下载验证程序
在天问Block插入USB左边的TypeC口下载这个程序,再插入右侧的USB口,打开软件监视器。上位机波特率设置成115200,点击“连接串口”。按下KEY1(RUN)键,程序运行,监视器显示如下图:
无标题.png

把程序中“delay(40);//延时时间修改53ms以上,就会进入中断”,延时delay(40)修改成54,延时54ms后,下载程序。
无标题.png
窗口看门狗进入中断,串口交替输出:
The program runs normally
Execute interrupt function

源代码在范例代码->CH32V外设代码范例->5.WWDG.hd

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|好好搭搭在线 ( © 好好搭搭在线 浙ICP备19030393号-1 )

GMT+8, 2024-5-8 08:47 , Processed in 0.358283 second(s), 25 queries .

Powered by Discuz!

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表