STM8S——watchdog(IWDG)

IWDG工作原理:

  1、当键值寄存器(IWDG_KR)中写入数值0xCC后,独立看门狗就会被启动,计数器开始从它的复位值0xFF开始递减计数,当计数减到0x00时就会产生一个复位信号。

  2、使用IWDG_PR和IWDG_RLR寄存器配独立看门狗。

  (1)IWDG_PR寄存器是用于选择驱动计数器时钟的预分频系数。

  (2)当KEY_REFRESH的数值(0xAA)写入到IWDG_KR寄存器时,独立看门狗将用IWDG_RLR的数值刷新计数器的内容,从而避免了产生看门狗的复位。

  3、IWDG_PR和IWDG_RLR寄存器具有写保护功能,要修改它们前,需首先在IWDG_KR寄存器写入KEY_ACCESS代码(0x55);在IWDG_KR写入0xAA将恢复写保护状态。

 IWDG工作细节:

1、为了避免程序忙跑跑死了没反应,加上一个看门狗watchdog实时监控着程序,一旦程序没有在规定的时间喂狗,则狗叫使得单片机复位。

2、Independent watchdog(IWDG)内部有时钟源(128kHz),所以即使主时钟挂了watchdog还是能继续工作的。

   另外还有个Window watchdog (WWDG),比IWDG复杂得多,我们没有采用。

3、由于内部是128kHz,所以watchdog能允许的最大延迟时间为510ms(当RL[7:0]= 0xFF时),最小延迟时间为2ms(当RL[7:0]= 0x00时);我们选取510ms。

  也就是说一旦打开看门狗,最迟每隔510ms就要进行喂狗操作,否则看门狗将会打开复位。

4、看门狗的实现不难,难点在于怎样验证自己设置的看门狗是否正确,难点在与想办法测试watchdog。

   方法是在while(1)的循环里延时510ms以上(如延时600ms),通过对相关寄存器特征值的显示查看,来判断单片机是否被复位,若被复位则验证成功。

5、值得注意的是,开门狗一旦打开就无法关闭,只有通过不断的喂狗来防止复位。

6、下面给出代码思路并且附带详细注释:

   由于延时函数如果延时太久会无法实现喂狗操作,所以应该在原来的Delay1ms()函数的基础上,再另外定义一个newDelay()函数,目的是每次延时250ms时(即调用Delay1ms(250))喂狗;

  1 /*-- private variable --*/
  2 __IO uint32_t space_reloadTM = 250;//define every after 250 ms reload IWDG
  3 
  4 /*-- private function --*/
  5 void NewDelay(__IO uint32_t nTime);//include reload IWDG
  6 
  7 static void IWDG_Config_Enable(void);//config and enable IWDG
  8 
  9 
 10 /*-- main function --*/
 11 int main()
 12 {
 13     IWDG_Config_Enable(); //config and enable IWDG 
 14 
 15     //for test
 16     while (1)
 17     {
 18         Delay1ms(600); //timeout and reset happend
 19         
 20         /*-- never runs here --*/
 21       
 22         //Reload IWDG counter
 23         IWDG_ReloadCounter();
 24     }
 25 }
 26 
 27 
 28 
 29 void NewDelay(__IO uint32_t nTime)
 30 {
 31     uint32_t time_divisor = nTime/space_reloadTM;
 32     uint32_t time_remainder = nTime%space_reloadTM;
 33     uint8_t i;
 34     
 35     /* every after 250ms reload IWDG */
 36     for(i=0;i<time_divisor;i++)
 37     {
 38         Delay1ms(space_reloadTM);
 39         //Reload IWDG counter
 40         IWDG_ReloadCounter();
 41     }
 42     
 43     /* delay the remain time */
 44     Delay1ms(time_remainder);
 45     //Reload IWDG counter
 46     IWDG_ReloadCounter();
 47 }
 48 /*
 49 void Delay1ms(__IO uint32_t nTime)
 50 {
 51   TimingDelay = nTime;
 52 
 53   while (TimingDelay != 0);
 54 }
 55 */
 56 
 57 
 58 
 59 /**
 60  * @brief  Configures the IWDG to generate a Reset if it is not refreshed at the
 61  *         correct time.
 62  * @param  None
 63  * @retval None
 64  */
 65 static void IWDG_Config_Enable(void)
 66 {
 67     /* Check if the system has resumed from IWDG reset */
 68     if (RST_GetFlagStatus(RST_FLAG_IWDGF) != RESET)
 69     {
 70         printf("\n\r");
 71         uart2str(uartbuff,RST->SR,8,2,'0');   //output RST register
 72         printf("Timeout, RST_SR=%s\n\r",uartbuff);
 73         
 74         printf("timeout!!!");
 75         
 76         /* IWDGF flag set */
 77         /* Clear IWDGF Flag */
 78         RST_ClearFlag(RST_FLAG_IWDGF);
 79     }
 80     else
 81     {
 82         //IWDGF flag is not set
 83     }
 84     
 85     
 86     /* --- IWDG Configuration --- */
 87     
 88     /* Enable IWDG (the LSI oscillator will be enabled by hardware) */
 89     IWDG_Enable(); //0xCC
 90     
 91     /* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency
 92      dispersion) */
 93     /* Enable write access to IWDG_PR and IWDG_RLR registers */
 94     IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //0x55
 95     
 96     /* IWDG counter clock: LSI/128 */
 97     IWDG_SetPrescaler(IWDG_Prescaler_128);
 98     
 99     /* Set counter reload value to obtain 250ms IWDG Timeout.
100      Counter Reload Value = 250ms/IWDG counter clock period
101      = 250ms / (LSI/128)
102      = 0.25s / (LsiFreq/128)
103      = LsiFreq/(128 * 4)
104      = LsiFreq/512
105      */
106     IWDG_SetReload((uint8_t)(0xFF));//510ms
107     
108     /* Reload IWDG counter */
109     IWDG_ReloadCounter(); //0xAA
110 }

   为了验证代码的可实现性,故意在主函数中调用Delay1ms(600),所以正确的执行结果应该是:执行Delay1ms(600),watchdog启动复位,输出timeout之类的提示;

   其中证明是否是watchdog启动的复位:查看RST->SR(Reset status register)中Bit1的值,为1表示An IWDG reset occurred,为0表示No IWDG reset occurred。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开源FPGA

基于Verilog HDL的二进制转BCD码实现

       在项目设计中,经常需要显示一些数值,比如温湿度,时间等等。在数字电路中数据都是用二进制的形式存储,要想显示就需要进行转换,对于一个两位的数值,对1...

16710
来自专栏分布式系统进阶

Librdkafka的操作处理队列

32120
来自专栏潇涧技术专栏

Lint Tool Analysis (2)

本系列的几篇源码分析文档意义不大,如果你正好也在研究lint源码,或者你想知道前面自定义lint规则中提出的那几个问题,抑或你只是想大致了解下lint的源码都有...

20910
来自专栏开发 & 算法杂谈

Intel Pin-JIT模式和Probe模式下库函数的替换

这篇文章主要介绍一下Intel Pin在JIT模式和Probe模式下对库换数的替换,以及实现中有哪写需要注意的地方。

28060
来自专栏jeremy的技术点滴

Java监听目录文件变更

42470
来自专栏程序猿

SQL Server基础SQL脚本之Group By

代码大概80行左右 本系列,几乎都是代码,记得当时写的时候用的是微软的官方实例数据库AdventureWorks_Data.mdf、AdventureWork...

22850
来自专栏码农分享

4.1、苏宁百万级商品爬取 代码讲解 索引建立

Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。

16230
来自专栏Java成神之路

Java企业微信开发_04_消息推送之发送消息(主动)

(1)流程不同:发送消息是第三方服务器主动通知微信服务器向用户发消息。而被动回复消息是 用户发送消息之后,微信服务器将消息传递给 第三方服务器,第三方服务器接收...

58450
来自专栏菩提树下的杨过

[转自JeffreyZhao]在LINQ to SQL中使用Translate方法以及修改查询用SQL

目前LINQ to SQL的资料不多——老赵的意思是,目前能找到的资料都难以摆脱“官方用法”的“阴影”。LINQ to SQL最权威的资料自然是MSDN,但是M...

21850
来自专栏web开发

java导出Excel表格

最近自己着手写了一个前后端分离的后台管理系统(主要是写着玩,java还是熟悉一点,所以前后端均是自己写),后端使用的Java SpringMVC。后来想着在用户...

545100

扫码关注云+社区

领取腾讯云代金券