搜索
bottom↓
回复: 16

请问深入浅出中的实例7 如何改WDT唤醒呢

[复制链接]

出0入0汤圆

发表于 2014-4-10 10:54:49 | 显示全部楼层 |阅读模式
中断唤醒的键盘扫描

用WDT的中断模式来唤醒powerdown,但WDT这部分的设置始终搞不好,AVR132的文章看的迷糊,能否给出一个AVR STUDIO 的中断设置以及返回休眠的例子呢

出0入0汤圆

 楼主| 发表于 2014-4-10 15:03:13 | 显示全部楼层
用WDT中断来处理定时唤醒只是一个应用思路,直接作为键盘扫描并不合适。WDT没有在书中介绍,太遗憾了

出0入296汤圆

发表于 2014-4-11 10:28:38 | 显示全部楼层
chenxp99 发表于 2014-4-10 15:03
用WDT中断来处理定时唤醒只是一个应用思路,直接作为键盘扫描并不合适。WDT没有在书中介绍,太遗憾了 ...

将WDT配置为中断模式(只产生中断,不产生复位动作),然后写一个中断处理程序,这个程序里面什么都不用做,
简单说就是用这个WDT中断唤醒下系统而已。

出0入0汤圆

 楼主| 发表于 2014-4-11 11:47:07 | 显示全部楼层
本帖最后由 chenxp99 于 2014-4-11 11:59 编辑
Gorgon_Meducer 发表于 2014-4-11 10:28
将WDT配置为中断模式(只产生中断,不产生复位动作),然后写一个中断处理程序,这个程序里面什么都不用 ...


下面的设置代码,运行后完全没有反应,哪里出错了呢

  1. ISR(WDT_vect) {
  2.         if (lstate)
  3.         {
  4.                 PORTC |= (1<<PC5);
  5.                 lstate = 0;
  6.         }
  7.         else
  8.         {
  9.                 PORTC &= ~(1<<PC5);
  10.                 lstate = 1;
  11.         }
  12. }

  13. main
  14.         ......
  15.         lstate=1;

  16.         cli();
  17.         wdt_reset();
  18.         WDTCSR |= (1<<WDCE)|(1<<WDE);
  19.         WDTCSR |= (1<<WDIE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0);        //8s interrupt mode
  20.         sei();
复制代码

出0入296汤圆

发表于 2014-4-11 11:52:48 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2014-4-11 12:00 编辑
chenxp99 发表于 2014-4-11 11:47
下面的设置代码,运行后完全没有反应,哪里出错了呢


芯片型号?你的WDT寄存器操作时序有问题,我记得WDT操作是有严格时序的。你这样用与或操作多半是
没法满足要求的。

这里是我以前写的一个WDT初始化代码的例子——没有初始化成中断模式,但是你可以修改下:
你要特别注意代码的注释——我从PDF上抄下来的。特别说明下,这里SAFE_ATOM_CODE是处理关中断开中断的,
以保证括号里面的代码执行的时候不会被中断处理程序打断。


  1. void Enable_Watchdog(void)
  2. {
  3.     SAFE_ATOM_CODE  (
  4.         //! In the same operation, write a logic one to WDCE and WDE.
  5.         WDTCR = BIT(WDCE) | BIT(WDE);  
  6.         /*! Within the next four clock cycles, in the same operation,
  7.          *  write the WDE and WDP bits asdesired, but with the WDCE bit cleared.
  8.          */
  9.         WDTCR = BIT(WDE) | (0x06 << WDP0);  //! 0.24s(3.0v) 0.22s(5.0v)
  10.     );
  11. }
复制代码


你要注意到,代码里面对看门狗寄存器的操作都是直接的写操作,并且有严格的顺序
1、同时对WDCE和WDE位置位
2、在步骤1之后的4个时钟周期内,同时置位WDE以及对应的WDP设置。

你的代码用了与或操作,也没有做中断保护,根本不可能保证上面的时序要求。另外特别说明下,对于某些编译器
比如GCC,即便你代码写成我这样,不开优化,生成的代码会非常笨,仍然会超过4个时钟周期的要求。

出0入0汤圆

 楼主| 发表于 2014-4-11 11:58:04 | 显示全部楼层
无效
  1.         cli();
  2.         wdt_reset();
  3.         WDTCSR = (1<<WDCE)|(1<<WDE);
  4.         WDTCSR = (1<<WDIE)|(1<<WDCE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0);
  5.         sei();
复制代码

闪烁频率不对
  1.         cli();
  2.         wdt_reset();
  3.         WDTCSR = (1<<WDCE)|(1<<WDE);
  4.         WDTCSR = (1<<WDIE)|(1<<WDCE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0);
  5.         sei();
复制代码

出0入296汤圆

发表于 2014-4-11 12:00:19 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2014-4-11 12:02 编辑
chenxp99 发表于 2014-4-11 11:58
无效

闪烁频率不对


看我前面的回复,你的操作时序是错的,你没有认真看数据手册。
频率不对是你没有正确的配置WDT的溢出时间参数,另外AVR的WDT的时间精度是+/-30%到+/-50%。手册上给出的时间只是参考,完全不当真

出0入0汤圆

 楼主| 发表于 2014-4-11 12:00:56 | 显示全部楼层
Gorgon_Meducer 发表于 2014-4-11 11:52
芯片型号?你的WDT寄存器操作时序有问题,我记得WDT操作是有严格时序的。你这样用与或操作多半是
没法满 ...

芯片是LGT8F880A

出0入296汤圆

发表于 2014-4-11 12:03:46 | 显示全部楼层

那你发错论坛了,亲,看门狗频率的问题,你要去问LGT,我这里看到的手册是参考AVR的,当然,他们号称是兼容的。

出0入0汤圆

 楼主| 发表于 2014-4-11 12:51:37 | 显示全部楼层
本帖最后由 chenxp99 于 2014-4-11 13:12 编辑
Gorgon_Meducer 发表于 2014-4-11 12:03
那你发错论坛了,亲,看门狗频率的问题,你要去问LGT,我这里看到的手册是参考AVR的,当然,他们号称是兼 ...


AVR的WDT的时间精度是+/-30%到+/-50%,这个精度也太夸张了。。。

那边超冷清,没人解答这么低级的问题,网上看到以前也有人有同样的问题,但都没结果。老外倒是有结果,误差蛮大的。谢谢傻孩子老师哈

WDT设置的溢出时间是8s,实际闪烁频率基本是1Hz,相当于实际溢出时间是0.5s,WDT的时钟误差不会这么大吧,会否还有别的问题存在呢

出0入296汤圆

发表于 2014-4-11 13:05:44 | 显示全部楼层
chenxp99 发表于 2014-4-11 12:51
AVR的WDT的时间精度是+/-30%到+/-50%,这个精度也太夸张了。。。

那边超冷清,没人解答这么低级的问题 ...

一般WDT都有自己专用的RC振荡器,我们叫做Internal RC Oscillator,这个振荡器目的就是给WDT提供一个
时钟,不需要精度高,所以一般也没有人特别去校准它,就算校准了,它的温票也很厉害,需要根据当前实际
温度来实时的校准……的确遇到过有项目需要用内部WDT的OSC来做的,我做过的……痛苦死了……

总之,对你有帮助就好。

出0入0汤圆

 楼主| 发表于 2014-9-3 21:28:50 | 显示全部楼层
Gorgon_Meducer 发表于 2014-4-11 10:28
将WDT配置为中断模式(只产生中断,不产生复位动作),然后写一个中断处理程序,这个程序里面什么都不用 ...

我在使用看门狗的中断模式来做长时段延时唤醒时,遇到一个现象,第一次可以正常唤醒(端口灯有闪),但继续休眠后再无法唤醒。WDT中断服务只有一句" i++;  "  i 已加volatile
        while (i<delay1)        //delay1
        {
                cli();
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);
                sleep_enable();
                sei();
                sleep_cpu();
          }
当处于唤醒状态时,WDT定时中断服务能够正常工作。后来将WDT中断服务里的 i++ 移至 主程序循环中才解决了重复休眠唤醒问题,但是为什么呢

        while (i<delay1)        //delay1
        {
                cli();
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);
                sleep_enable();
                sei();
                sleep_cpu();
                i++;
    }

也曾尝试在sleep_cpu()后面加入 延时200ms ,让全局变量 i 的(中断)修改和(主程序)读取操作不要挨的太近, 但没有效果(低主频)。猜测中断服务对变量的修改并没有被主程序读到,该如何解决呢

出0入296汤圆

发表于 2014-9-4 23:33:49 | 显示全部楼层
chenxp99 发表于 2014-9-3 21:28
我在使用看门狗的中断模式来做长时段延时唤醒时,遇到一个现象,第一次可以正常唤醒(端口灯有闪),但继 ...

没弄懂你的问题,你的问题究竟是休眠后无法唤醒还是重复唤醒?
请给出一个例子代码,描述期望现象,实际现象。

出0入0汤圆

 楼主| 发表于 2014-9-5 12:37:25 | 显示全部楼层
Gorgon_Meducer 发表于 2014-9-4 23:33
没弄懂你的问题,你的问题究竟是休眠后无法唤醒还是重复唤醒?
请给出一个例子代码,描述期望现象,实际 ...

希望重复唤醒

        volatile i;
        const delay1=1000;
        isr(wdt_vect)
        { i++;}

        main()
        {
            while (i<delay1)        //delay1
            {
                cli();
                set_sleep_mode(SLEEP_MODE_PWR_DOWN);
                sleep_enable();
                sei();
                sleep_cpu();
             }
        }

实际运行只唤醒了第一次

出0入296汤圆

发表于 2014-9-5 12:56:01 | 显示全部楼层
chenxp99 发表于 2014-9-5 12:37
希望重复唤醒

        volatile i;

在那个while里面toggle IO而不是用变量I,借助示波器来检查是否休眠了多次。

出0入0汤圆

 楼主| 发表于 2014-9-5 13:30:40 | 显示全部楼层
Gorgon_Meducer 发表于 2014-9-5 12:56
在那个while里面toggle IO而不是用变量I,借助示波器来检查是否休眠了多次。 ...

手头没示波器,我用PORT点灯看过,只亮了一次

出0入296汤圆

发表于 2014-9-5 20:19:31 | 显示全部楼层
chenxp99 发表于 2014-9-5 13:30
手头没示波器,我用PORT点灯看过,只亮了一次

toggle,不是单纯的置位或者清零,你可以进入前让灯保持亮的状态,然后休眠醒来后的toggle会
熄灭灯,如果灯一直是熄灭的,则可以判定是只进入了一次。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-3 03:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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