Forum: Compiler & IDEs Atmega644p + WDT + Sleepmode


von Ralle (Gast)


Lesenswert?

Hi,
wir wollen den 644p in den Sleepmode "Power-Down" schicken und mit dem 
WDT (geht laut Datenblatt) wieder aufwecken. Unsere Idee ist es keinen 
Reset machen zu lassen sondern in der ISR(WDT_vect) die sleepinstr. zu 
deaktivieren. Unsere Problems sind zum einen, das mit wdt_enable() es 
zwar kein Problem ist den WDT einzuschalten, er jedoch immer bei Ablauf 
einen Reset macht und nicht in die ISR springt. Was muessen wir tun um 
den Reset zu deaktivieren und die ISR zu aktivieren? Zum anderen wissen 
wir nicht, ob wir aus dem Power-Down direkt in die ISR von WDT springen 
koenen.
Hat da jemand schon Erfahrung??

von Peter D. (peda)


Lesenswert?

Ralle wrote:
> Unsere Problems sind zum einen, das mit wdt_enable() es
> zwar kein Problem ist den WDT einzuschalten, er jedoch immer bei Ablauf
> einen Reset macht und nicht in die ISR springt.

Das ist korrekt, dazu ist die Blackbox wdt_enable() gemacht.


> Was muessen wir tun um
> den Reset zu deaktivieren und die ISR zu aktivieren?

Das Datenblatt lesen und dann die nötigen Bits selber setzen.


> Hat da jemand schon Erfahrung??

Ich nicht (ich benutze keinen Batteriebetrieb, meine Geräte laufen alle 
am Stromnetz).


Peter

von Oliver B. (Gast)


Lesenswert?

> Unsere Problems sind zum einen, das mit wdt_enable() es
> zwar kein Problem ist den WDT einzuschalten, er jedoch immer bei Ablauf
> einen Reset macht und nicht in die ISR springt.

wdt_enable() setzt nicht nur die Prescaler-Bits, sondern auch WDE, 
wodurch ein Reset ausgelöst wird.

> Was muessen wir tun um den Reset zu deaktivieren und die ISR zu aktivieren?

Manuell die Prescaler-Bits sowie WDIE setzen, um den Watchdoginterrupt 
zu aktivieren.

> Zum anderen wissen wir nicht, ob wir aus dem Power-Down direkt in die ISR
> von WDT springen koenen.

Ja.

von Ralle (Gast)


Lesenswert?

Also wir machen es so:

  cli();
  MCUSR &= ~(1<<WDRF);
  WDTCSR |= (1<<WDCE);
  WDTCSR |= ((1<<WDIE) | (1<<WDP2)|(1<<WDP1)| (1<<WDP0));

  MCUSR &= ~(1<<WDRF);
  WDTCSR &= ~(1<<WDE);
  sei();

Also WDIE fuer Interrupt und WDE=0 fuer "kein Reset". Prescaler wird 
eingestellt. Funzt aber nicht. Macht ISR + Reset und ist sau schnell. 
Nicht wie in Prescaler eingestellt.

von Peter D. (peda)


Lesenswert?

Schmeiß mal die ganzen &=, |= raus.

Du mußt direkt zuweisen (=), damit die Timings (<4Takte) eingehalten 
werden.


Peter

von Ralle (Gast)


Lesenswert?

OK, schon besser.

  cli();
  MCUSR = ~(1<<WDRF);
  WDTCSR = (1<<WDCE) | (1<<WDE);
  WDTCSR = ((1<<WDIE) | (1<<WDP2)|(1<<WDP1)| (1<<WDP0));

  MCUSR = ~(1<<WDRF);
  WDTCSR = ~(1<<WDE);
  sei();

So gehts! Alle 2 Sec. wird ISR(WDT_vect) ausgefuehrt ohne 
anschliessenden Reset. Nur Interrupt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Du kannst auch einen avr-libc-Bugreport schreiben, damit diese
Funktionalität mal in <avr/wdt.h> mit aufgenommen wird.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.