Будить по кнопке на прерывание _И_ по WDT
- Войдите на сайт для отправки комментариев
Втр, 27/08/2013 - 20:01
Такая задача: в спящем режиме раз в 4 сек. кратковременно загорается светодиод. Ессно, раз в 4 секунды надо проснуться, мигнуть светиком, уснуть. Также есть кнопка, допустим на INT0 (D2) - если нажали кнопку, надо проснуться на некоторое время (допустим 3 секунды), в течение которого светик включен постоянно.
По отдельности работает. Вместе может очнуться только с WDT, жму кнопку а ничё не происходит. Что может быть?
#include <avr/sleep.h> #include <avr/power.h> #include <avr/wdt.h> int seconds=0; volatile boolean f_wdt=true, bActive=true; void pin2Interrupt(void){ detachInterrupt(0); digitalWrite(A0,HIGH); bActive=true; } ISR(WDT_vect){ if(!bActive && !f_wdt) f_wdt=true; } void enterSleep(void){ if(bActive){ attachInterrupt(0, pin2Interrupt, LOW); digitalWrite(A0,LOW); bActive=false; } set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); /* First thing to do is disable sleep. */ power_all_enable(); } void setup(){ pinMode(A0,OUTPUT); /* Clear the reset flag. */ MCUSR &= ~(1<<WDRF); /* In order to change WDE or the prescaler, we need to * set WDCE (This will allow updates for 4 clock cycles).*/ WDTCSR |= (1<<WDCE) | (1<<WDE); /* set new watchdog timeout prescaler value */ WDTCSR = 1<<WDP3; /* 4.0 seconds */ /* Enable the WDT interrupt (note no reset). */ WDTCSR |= _BV(WDIE); } void loop(){ if(f_wdt && !bActive){ // waked by WDT /* Toggle the LED */ digitalWrite(A0,HIGH); delay(50); digitalWrite(A0,LOW); f_wdt = false; enterSleep(); } if(bActive){ // waked from btn delay(1000); seconds++; if(seconds == 3){ seconds = 0; enterSleep(); } } }
Посмотри пост №9 http://cyber-place.ru/showthread.php?t=325
Там в автономном устройстве есть кнопка , IR датчик на прерываниях и программный таймер .
Всё просыпается по кнопке или по сигналу с IR.
( ... void wakeupFunction() ... )
Я так понимаю, там два прерывания - D2 (ИК приёмник) и D3 (кнопка), то есть внутри самого МК никакого прерывания не происходит. неужто это возможно только снаружи? неохота городить внешний генератор на 4 секунды, я думал можно заставить заниматься этим watchdog.
fot таки предложил просто два прерывания. А тем временем мне всё же удалось замоделить; выкладываю, может кому понадобится.
WDTCSR = 1<<WDP0 | 1<<WDP3; // WDT interval - интервал просыпания (смотреть тут)
if(seconds == 5) // time to keep ON state - время, которое следует выждать перед тем как заснуть