请问深入浅出中的实例7 如何改WDT唤醒呢
中断唤醒的键盘扫描用WDT的中断模式来唤醒powerdown,但WDT这部分的设置始终搞不好,AVR132的文章看的迷糊,能否给出一个AVR STUDIO 的中断设置以及返回休眠的例子呢
用WDT中断来处理定时唤醒只是一个应用思路,直接作为键盘扫描并不合适。WDT没有在书中介绍,太遗憾了 chenxp99 发表于 2014-4-10 15:03
用WDT中断来处理定时唤醒只是一个应用思路,直接作为键盘扫描并不合适。WDT没有在书中介绍,太遗憾了 ...
将WDT配置为中断模式(只产生中断,不产生复位动作),然后写一个中断处理程序,这个程序里面什么都不用做,
简单说就是用这个WDT中断唤醒下系统而已。 本帖最后由 chenxp99 于 2014-4-11 11:59 编辑
Gorgon_Meducer 发表于 2014-4-11 10:28
将WDT配置为中断模式(只产生中断,不产生复位动作),然后写一个中断处理程序,这个程序里面什么都不用 ...
下面的设置代码,运行后完全没有反应,哪里出错了呢
ISR(WDT_vect) {
if (lstate)
{
PORTC |= (1<<PC5);
lstate = 0;
}
else
{
PORTC &= ~(1<<PC5);
lstate = 1;
}
}
main
......
lstate=1;
cli();
wdt_reset();
WDTCSR |= (1<<WDCE)|(1<<WDE);
WDTCSR |= (1<<WDIE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0); //8s interrupt mode
sei();
本帖最后由 Gorgon_Meducer 于 2014-4-11 12:00 编辑
chenxp99 发表于 2014-4-11 11:47
下面的设置代码,运行后完全没有反应,哪里出错了呢
芯片型号?你的WDT寄存器操作时序有问题,我记得WDT操作是有严格时序的。你这样用与或操作多半是
没法满足要求的。
这里是我以前写的一个WDT初始化代码的例子——没有初始化成中断模式,但是你可以修改下:
你要特别注意代码的注释——我从PDF上抄下来的。特别说明下,这里SAFE_ATOM_CODE是处理关中断开中断的,
以保证括号里面的代码执行的时候不会被中断处理程序打断。
void Enable_Watchdog(void)
{
SAFE_ATOM_CODE(
//! In the same operation, write a logic one to WDCE and WDE.
WDTCR = BIT(WDCE) | BIT(WDE);
/*! Within the next four clock cycles, in the same operation,
*write the WDE and WDP bits asdesired, but with the WDCE bit cleared.
*/
WDTCR = BIT(WDE) | (0x06 << WDP0);//! 0.24s(3.0v) 0.22s(5.0v)
);
}
你要注意到,代码里面对看门狗寄存器的操作都是直接的写操作,并且有严格的顺序
1、同时对WDCE和WDE位置位
2、在步骤1之后的4个时钟周期内,同时置位WDE以及对应的WDP设置。
你的代码用了与或操作,也没有做中断保护,根本不可能保证上面的时序要求。另外特别说明下,对于某些编译器
比如GCC,即便你代码写成我这样,不开优化,生成的代码会非常笨,仍然会超过4个时钟周期的要求。 无效
cli();
wdt_reset();
WDTCSR = (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDIE)|(1<<WDCE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0);
sei();
闪烁频率不对
cli();
wdt_reset();
WDTCSR = (1<<WDCE)|(1<<WDE);
WDTCSR = (1<<WDIE)|(1<<WDCE)|(0<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(1<<WDP0);
sei();
本帖最后由 Gorgon_Meducer 于 2014-4-11 12:02 编辑
chenxp99 发表于 2014-4-11 11:58
无效
闪烁频率不对
看我前面的回复,你的操作时序是错的,你没有认真看数据手册。
频率不对是你没有正确的配置WDT的溢出时间参数,另外AVR的WDT的时间精度是+/-30%到+/-50%。手册上给出的时间只是参考,完全不当真 Gorgon_Meducer 发表于 2014-4-11 11:52
芯片型号?你的WDT寄存器操作时序有问题,我记得WDT操作是有严格时序的。你这样用与或操作多半是
没法满 ...
芯片是LGT8F880A chenxp99 发表于 2014-4-11 12:00
芯片是LGT8F880A
那你发错论坛了,亲,看门狗频率的问题,你要去问LGT,我这里看到的手册是参考AVR的,当然,他们号称是兼容的。 本帖最后由 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的时钟误差不会这么大吧,会否还有别的问题存在呢 chenxp99 发表于 2014-4-11 12:51
AVR的WDT的时间精度是+/-30%到+/-50%,这个精度也太夸张了。。。
那边超冷清,没人解答这么低级的问题 ...
一般WDT都有自己专用的RC振荡器,我们叫做Internal RC Oscillator,这个振荡器目的就是给WDT提供一个
时钟,不需要精度高,所以一般也没有人特别去校准它,就算校准了,它的温票也很厉害,需要根据当前实际
温度来实时的校准……的确遇到过有项目需要用内部WDT的OSC来做的,我做过的……痛苦死了……
总之,对你有帮助就好。 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 的(中断)修改和(主程序)读取操作不要挨的太近, 但没有效果(低主频)。猜测中断服务对变量的修改并没有被主程序读到,该如何解决呢
chenxp99 发表于 2014-9-3 21:28
我在使用看门狗的中断模式来做长时段延时唤醒时,遇到一个现象,第一次可以正常唤醒(端口灯有闪),但继 ...
没弄懂你的问题,你的问题究竟是休眠后无法唤醒还是重复唤醒?
请给出一个例子代码,描述期望现象,实际现象。 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();
}
}
实际运行只唤醒了第一次 chenxp99 发表于 2014-9-5 12:37
希望重复唤醒
volatile i;
在那个while里面toggle IO而不是用变量I,借助示波器来检查是否休眠了多次。 Gorgon_Meducer 发表于 2014-9-5 12:56
在那个while里面toggle IO而不是用变量I,借助示波器来检查是否休眠了多次。 ...
手头没示波器,我用PORT点灯看过,只亮了一次 chenxp99 发表于 2014-9-5 13:30
手头没示波器,我用PORT点灯看过,只亮了一次
toggle,不是单纯的置位或者清零,你可以进入前让灯保持亮的状态,然后休眠醒来后的toggle会
熄灭灯,如果灯一直是熄灭的,则可以判定是只进入了一次。
页:
[1]