OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11646|回复: 19

窗口看门狗的开启与提前唤醒中断顺序问题

[复制链接]

9

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2015-8-18
在线时间
17 小时
发表于 2016-3-4 15:21:02 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 kingpage 于 2016-3-4 15:23 编辑

按照原子所提供的窗口看门狗的代码如下:
[mw_shl_code=c,true]//保存WWDG计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
//初始化窗口看门狗        
//tr   :T[6:0],计数器值
//wr   :W[6:0],窗口值
//fprer:分频系数(WDGTB),仅最低2位有效
//Fwwdg=PCLK1/(4096*2^fprer).
void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{   
        RCC->APB1ENR|=1<<11;         //使能wwdg时钟
        WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.     
        WWDG->CFR|=fprer<<7;    //PCLK1/4096再除2^fprer
        WWDG->CFR&=0XFF80;      
        WWDG->CFR|=wr;                     //设定窗口值      
        WWDG->CR|=WWDG_CNT;         //设定计数器值
       
        WWDG->CR|=1<<7;                  //开启看门狗  
   
        MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2     
        WWDG->SR=0X00;                         //清除提前唤醒中断标志位
        WWDG->CFR|=1<<9;        //使能提前唤醒中断
       
}
//重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
{
        WWDG->CR =(cnt&0x7F);//重设置7位计数器
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{      
        WWDG_Set_Counter(WWDG_CNT);//重设窗口看门狗的值!         
        WWDG->SR=0X00;//清除提前唤醒中断标志位
        LED1=!LED1;
}[/mw_shl_code]
其中,在看门狗初始化WWDG_Init函数中,按照这样的代码顺序是没问题的,能正常地进入WWDG_IRQHandler函数进行喂狗。但如果把WWDG_Init函数中的WWDG->CR|=1<<7; //开启看门狗.这一行代码的位置放到同样是WWDG_Init函数:
[mw_shl_code=c,true]MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2
WWDG->SR=0X00; //清除提前唤醒中断标志位
WWDG->CFR|=1<<9; //使能提前唤醒中断[/mw_shl_code]
中的任何一行代码后面,例如初始化代码改为:
[mw_shl_code=c,true]void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{   
        RCC->APB1ENR|=1<<11;         //使能wwdg时钟
        WWDG_CNT=tr&WWDG_CNT;   //初始化WWDG_CNT.     
        WWDG->CFR|=fprer<<7;    //PCLK1/4096再除2^fprer
        WWDG->CFR&=0XFF80;      
        WWDG->CFR|=wr;                     //设定窗口值      
        WWDG->CR|=WWDG_CNT;         //设定计数器值
   
        MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2     
        WWDG->SR=0X00;                         //清除提前唤醒中断标志位
        WWDG->CFR|=1<<9;        //使能提前唤醒中断

        WWDG->CR|=1<<7;                  //开启看门狗
       
} [/mw_shl_code]
看门狗就会出现不断地产生复位的情况。按照我的理解应该是把看门狗所有的配置(包括它相关的寄存器以及中断分组等)都设置好,再开启看门狗才是个正确的代码运行顺序啊,为何"开启看门狗"这句代码放在后面就会产生不断复位的问题?

最佳答案

查看完整内容[请看2#楼]

使能窗口看门狗的时候,WWDG_SR中的EWIF位就马上被置位了(具体为什么我也不清楚),加上我们使能了中断,所以程序会马上进入中断。我们在中断服务程序里面喂狗,按原子哥的看门狗例程[mw_shl_code=c,true]WWDG_Init(0X7F,0X5F,3); //计数器值为7f,窗口寄存器为5f,分频数为8 [/mw_shl_code] ,窗口的值比计数器的值小(我们的中断服务程序是在窗口外重新加载计数器),所以就马上复位了。 解决方法有两个: ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

261

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2075
金钱
2075
注册时间
2014-2-20
在线时间
284 小时
发表于 2016-3-4 15:21:03 | 显示全部楼层
本帖最后由 Da Wen 于 2016-3-10 09:33 编辑

  使能窗口看门狗的时候,WWDG_SR中的EWIF位就马上被置位了(具体为什么我也不清楚),加上我们使能了中断,所以程序会马上进入中断。我们在中断服务程序里面喂狗,按原子哥的看门狗例程[mw_shl_code=c,true]WWDG_Init(0X7F,0X5F,3);        //计数器值为7f,窗口寄存器为5f,分频数为8         [/mw_shl_code]  ,窗口的值比计数器的值小(我们的中断服务程序是在窗口外重新加载计数器),所以就马上复位了。
解决方法有两个:
一、在初始化看门狗的时候,窗口的值比计数器的重装值大。[mw_shl_code=c,true]WWDG_Init(0x70,0x7e,WWDG_Prescaler_8);[/mw_shl_code]
二、在使能看门狗之后,先清除一下中断标志位,然后再使能中断。(这时候窗口的值在初始化的时候就可以比计数器的值小)
[mw_shl_code=c,true]uint8_t WWDG_CNT = 0x7f;

void WWDG_Init(uint8_t tr,uint8_t wr,uint32_t fprer)
{
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
        
        WWDG_CNT = tr & WWDG_CNT; ///设置重装值
        WWDG_SetPrescaler(fprer);//设置分频系数
        
        WWDG_SetWindowValue(wr);//设置窗口的值
        
        
        WWDG_NVIC_Init(); //配置中断优先级
        
        WWDG_Enable(WWDG_CNT);//使能看门狗
        WWDG_ClearFlag(); //清除中断标志位
        WWDG_EnableIT(); //使能中断
}[/mw_shl_code]
回复

使用道具 举报

0

主题

2

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2016-1-16
在线时间
12 小时
发表于 2016-3-4 18:22:53 | 显示全部楼层
我也是刚碰到这样的问题
回复

使用道具 举报

9

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2015-8-18
在线时间
17 小时
 楼主| 发表于 2016-3-4 23:38:49 | 显示全部楼层
caojiasheng 发表于 2016-3-4 18:22
我也是刚碰到这样的问题

原来不止我一个碰上这问题了。有没有高手解答一下呢?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2016-3-5 22:57:55 | 显示全部楼层
窗口看门狗的代码,不要随意改,很容易出问题。至于为什么,我也不知道
回复

使用道具 举报

9

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2015-8-18
在线时间
17 小时
 楼主| 发表于 2016-3-7 22:22:09 | 显示全部楼层
正点原子 发表于 2016-3-5 22:57
窗口看门狗的代码,不要随意改,很容易出问题。至于为什么,我也不知道

原来连原子哥也不知道
回复

使用道具 举报

65

主题

486

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2109
金钱
2109
注册时间
2015-11-14
在线时间
515 小时
发表于 2016-3-7 23:47:47 | 显示全部楼层
一开始看到问题时我也蒙了,然后往下拉,看到原子哥也不会我就开心了
回复

使用道具 举报

3

主题

261

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2075
金钱
2075
注册时间
2014-2-20
在线时间
284 小时
发表于 2016-3-8 11:31:31 | 显示全部楼层
简单来说,要么就是窗口值比重装值大,但是这样感觉好像很浪费资源。要么就是顺序按照  使能看门狗->清标志位->使能中断
回复

使用道具 举报

9

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2015-8-18
在线时间
17 小时
 楼主| 发表于 2016-7-6 00:14:10 | 显示全部楼层
Da Wen 发表于 2016-3-4 15:21
使能窗口看门狗的时候,WWDG_SR中的EWIF位就马上被置位了(具体为什么我也不清楚),加上我们使能了中 ...

工作原因,一直加班了好几个月,现在才有时间看你的回复。看了你的回复后,终于明白原因何在了,非常感谢。
回复

使用道具 举报

20

主题

108

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
375
金钱
375
注册时间
2016-9-26
在线时间
59 小时
发表于 2016-9-26 10:59:13 | 显示全部楼层
Da Wen 发表于 2016-3-8 11:31
简单来说,要么就是窗口值比重装值大,但是这样感觉好像很浪费资源。要么就是顺序按照  使能看门狗->清标志 ...

你好,我有个问题,我参照原子哥的例程在自己写窗口看门狗的代码时候不小心想当然把“清除标志位”放在了“使能窗口看门狗”之前了,事实证明这样是错误的。请问窗口看门狗哦配置逻辑顺序为啥是你说的这个顺序呢?
回复

使用道具 举报

3

主题

261

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2075
金钱
2075
注册时间
2014-2-20
在线时间
284 小时
发表于 2016-10-21 10:59:46 | 显示全部楼层
单井老头 发表于 2016-9-26 10:59
你好,我有个问题,我参照原子哥的例程在自己写窗口看门狗的代码时候不小心想当然把“清除标志位”放在了 ...

2楼有说,你看看
回复

使用道具 举报

20

主题

108

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
375
金钱
375
注册时间
2016-9-26
在线时间
59 小时
发表于 2016-10-21 11:23:14 | 显示全部楼层
Da Wen 发表于 2016-10-21 10:59
2楼有说,你看看

好人一生平安
回复

使用道具 举报

42

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
448
金钱
448
注册时间
2016-3-8
在线时间
57 小时
发表于 2016-11-27 11:42:40 | 显示全部楼层
WWDG_SR中的EWIF位是硬件置1,开启了窗口中断后,只要计数到0x40该位就会被硬件自动置1,但是清0需要软件来做而且必须每次喂狗后都要清0
回复

使用道具 举报

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2016-11-29
在线时间
32 小时
发表于 2016-12-12 16:36:47 | 显示全部楼层
本帖最后由 yuxuhui 于 2016-12-12 16:40 编辑

二楼说的....
回复

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2017-2-8
在线时间
10 小时
发表于 2017-2-8 19:29:09 | 显示全部楼层
表示使用二楼的第二种方法还是不行。
然后自己结合楼上所说的,主要在于设定计数器值时要保证窗口值比当前计数器值大这么一点:
1,在初始化函数中,设定计数器值前尽量保证窗口值比计数器当前值大,设定计数器值后再设定窗口值。(复位后默认都为0x7f,所以可以先开启窗口看门狗,同时设定计数器初值,完了再设定窗口值)
2,在提前唤醒中断中,喂狗之前先设定窗口值大于喂狗值,然后退出中断前回复窗口值,为此要浪费一个外部变量。
这个方法经过多次测试。开启窗口看门狗可以放在初始化函数的多个地方不受影响。
但总是有点担心是否失去了“窗口”的效果。
另外,感觉原子哥的本讲内容中,窗口看门狗的实验效果那个地方有逻辑上的问题。
欢迎指正。
回复

使用道具 举报

7

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
123
金钱
123
注册时间
2016-12-2
在线时间
35 小时
发表于 2017-2-24 15:52:05 | 显示全部楼层
顶上去。学习了。
回复

使用道具 举报

4

主题

66

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3324
金钱
3324
注册时间
2016-11-9
在线时间
296 小时
发表于 2017-3-7 13:37:55 | 显示全部楼层
遇到同样的问题了
回复

使用道具 举报

8

主题

56

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
224
金钱
224
注册时间
2019-4-17
在线时间
34 小时
发表于 2020-4-1 16:10:22 | 显示全部楼层
俺也碰到了
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2021-11-24
在线时间
2 小时
发表于 2022-7-28 19:29:44 | 显示全部楼层
wahahahaha 发表于 2017-2-8 19:29
表示使用二楼的第二种方法还是不行。
然后自己结合楼上所说的,主要在于设定计数器值时要保证窗口值比当前 ...

我也是这个情况,不明白原理是啥,它是连中断服务函数都没进,我怀疑只要更新计数器的值它就认为喂了一次狗,然后因为比上窗口大所以引发复位。但是我把主函数的延时函数去掉也就好了,不知道为啥?
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2023-6-19
在线时间
4 小时
发表于 2023-11-25 20:12:09 | 显示全部楼层
Da Wen 发表于 2016-3-4 15:21
使能窗口看门狗的时候,WWDG_SR中的EWIF位就马上被置位了(具体为什么我也不清楚),加上我们使能了中 ...

感觉楼主说的对,暂且将以下四句命名为ABCD
WWDG_Enable(WWDG_CNT); // A
WWDG_ClearFlag();                 // B
WWDG_NVIC_Init();                 // C
WWDG_EnableIT();                  // D
看门狗复位情况:
1.CR寄存器T[6:0]值大于窗口值时喂狗
2.CR寄存器T[6:0]值减到了0X3F
注:CR寄存器的WDGA位不置1,也就是不使能看门狗,即便发生以上情况也是不复位的;CR寄存器的WDGA位不置1,T[6:0]仍是在递减的。
经过测试发现
正常顺序:ABCD、BABCD、BCABD
异常顺序:BACD、BCAD、BCDA、BCDAB,会一直复位
应该如楼主所说,使能看门狗时,SR中的中断标志EWIF位会置1(原因不知道),所以使能看门狗之后必须先清除中断标志位,再开启中断,所以BABCD和BCABD的顺序是可以的
异常顺序中,使能看门狗,EWIF位置1,不清除的话,一旦被中断检测到,立刻进入中断函数,若在函数中喂狗,此时会出现复位的第一种情况,就导致在WWDG_Init()函数执行期间一直复位,无法进去主程序的死循环中,LED0常亮。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 16:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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