www.mikrocontroller.net

Forum: Compiler & IDEs Watchdog First Time


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich hab vorhin einen Tipp bekommen, dass ich das Aufwecken meine 
ATmega88 auch gut mit einem Watchdog lösen kann.

Ich hab mich jetzt mal ein bissl eingelesen und benutze jetzt die wdt.h!

Mein Programm-Code soll eigentlich nur den Watchdocg überprüfen.

Dieser wird auf 8s Prescaler eingestellt und soll wenn er in die ISR 
springt eine Variable setzen, die anschließend im Hauptprogramm eine LED 
für eine Sekunde leuchten lassen soll.

Davor soll der IC in den Power Down Mode gesetzt werden. Der Watchdog 
sollte diesen ja eigentlich aufwecken.

Nun hier mal mein Programm-Code... das Problem ist, die LED leuchtet 
nicht :(

// Hauptprogramm===================================================================================


int main(void)

{
  //initLDR();              // LDR initialiseren
  
  //ACSR = 0x80;            // AD ausschalten
  
  wdt_enable(WDTO_8S);

  sei();                // Interrupts aktivieren
    
  while(1)
  
  {  
        wdt_reset();
    
    OCR2B = 0;                       // Dummyzugriff
        while((ASSR & (1<< OCR2BUB)));   // Warte auf das Ende des Zugriffs
 
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_mode();                   // in den Schlafmodus wechseln

    if (GO==1)
    
    {            
      SET_BIT(DDRB, DDB2);            
      CLR_BIT(PORTB, PB2);    // LED einschalten, falls an

      _delay_ms(1000);
    }
  }      
}


//================================================================================================

//Watchdog Interrupt==============================================================================

ISR (WDT_vect)      // Interrupt Service Rountine Timer Overflow 2

{
  GO = 1;
  SET_BIT(DDRB, DDB2);
  SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
}



Danke euch schonmal!

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Geht der AVR überhaupt in den Sleep Modus (Hinweis: Stromaufnahme 
messen)?

Wenn nein, dann nachsehen, wie kommt das Programm über diese Stelle?
> while((ASSR & (1<< OCR2BUB)));   // Warte auf das Ende des Zugriffs

Und nachsehen, wie GO definiert ist (volatile?).

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja GO hab ich als volatile definiert... richtig so oder?

aber stimmt ASSR hat gar keinen Bezug mehr... ist noch n Fragment eines 
anderen Codes. Den Dummyzugriff und so habe ich aus dem AVR-GCC Tutorial 
übernommen.

Also Stromverbrauch ist konstant bei 12mA... tut sich gar nichts. Hab 
jetzt einfach mal die zwei zeilen OCR2B und ASSR rausgelöscht

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für den Atmega8 habe ich gerade ein kleines Beispiel dazu geschrieben.
http://www.mikrocontroller.net/articles/Pollin_Fun...

Das ist auch für den Atmega89 übersetzbar und kann dir vielleicht die 
Erleuchtung bringen. Ich selbst kann es aber nicht für den Atmega88 
testen, weil ich keinen Atmega88 zur Hand habe.

Die Anzeige per LED habe ich auf PD5 gemacht. Die LED ist an PD5 so 
angeschlossen:

PD5 o--------###-------->|--------o GND
        Vorwiderstand  LED

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow echt super Sache was du da aufbaust ;)

Aber wo ist denn deine ISR?

Brauch man die nicht beim Watchdog? Die ISR (WDT_vect)?

Wo springt denn das Programm hin, wenn es aufgeweckt wird?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau ich nach. Ich habe wohl noch einen Bug drin!

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay... für was braucht man aber dann die ISR (WDT_vect)?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> okay... für was braucht man aber dann die ISR (WDT_vect)?

Mit einer Watchdog-Interrupt ISR spart man sich den RESET.

Den Atmega8 habe ich schlecht gewählt, denn der hat keinen 
Interruptvektor für den Watchdog, den ich auf eine eigene ISR umlenken 
kann. Beim Atmega8 wird durch den Watchdog ein RESET ausgelöst. Man kann 
die Resetursache dann abfragen (um andere Resetursachen 
auszuschliessen). Das ändert aber nix daran, dass das Programm von vorne 
neu gestartet wird und man in seinen Variablen und Programmabläufen 
darauf Rücksicht nehmen muss. Diesen Neustart habe ich jetzt im Artikel 
dokumentiert.

Ich muss mal suchen, ob ich einen AVR mit Watchdog-Interrupt habe und 
den Artikel ergänzen kann. Vielleicht der Attiny2313?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay du meinst also, wenn der Watchdog auslöst, resettet das ganze 
Programm oder wie? Und wenn man davor immer den Watchdog_Reset reinhaut, 
tut er das nicht!

Ich hab gelesen, dass wenn der WD auslöst, dieser dann nach dem Sleep 
Befehl einfach weiter macht... und wenn die while-Schleife durchgelaufen 
ist, der sleep-befehlt ja wieder kommt und er schlafen geht.

und iwo hab ich noch gelesen, dass wenn der WD zuschlägt, ein Interrupt 
ausgelöst wird und dieser interrupt dann so lange zeit hat abgearbeitet 
zu werden, bis theoretisch ein neuer WD auslöst und diesmal entgültig 
das system resettet ode rbist einfach der WD_Reset gesetzt wurde.

stimmt das in etwa?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, mit dem Attiny2313 kann man den Watchdog Interrupt so aufsetzen, 
dass kein System Reset ausgeführt wird. Der Artikel ist entsprechend 
ergänzt.
Und nicht wundern: Was beim Atmega88 WDT_vect heisst, heisst beim 
Attiny2313 WDT_OVERFLOW_vect.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Okay du meinst also, wenn der Watchdog auslöst, resettet das ganze
> Programm oder wie? Und wenn man davor immer den Watchdog_Reset reinhaut,
> tut er das nicht!

Ja bei dem Dino Atmega8 ist das so. Den Watchdog Reset hat man im 
Sleep Modsu nicht zur Verfügung bzw. verlässt man sich ja gerade darauf, 
dass der Watchdog auslöst.

Kein Reset ist beim Attiny2313 und beim Atmega88 (und anderen) 
einstellbar, wenn die entsprechend konfiguriert werden.

> Ich hab gelesen, dass wenn der WD auslöst, dieser dann nach dem Sleep
> Befehl einfach weiter macht... und wenn die while-Schleife durchgelaufen
> ist, der sleep-befehlt ja wieder kommt und er schlafen geht.

Bei obigen "modernen" AVRs ist das möglich!

> und iwo hab ich noch gelesen, dass wenn der WD zuschlägt, ein Interrupt
> ausgelöst wird und dieser interrupt dann so lange zeit hat abgearbeitet
> zu werden, bis theoretisch ein neuer WD auslöst und diesmal entgültig
> das system resettet ode rbist einfach der WD_Reset gesetzt wurde.

Ja das ist in etwas richtig, wenn WDTCSR für den Interrupt and System 
Reset Mode konfiguriert wurde, d.h. WDIE und WDE gesetzt sind.

Der erste anspringende Watchdog ruft die ISR auf und löscht das WDIE Bit 
und der nächste führt zu einem System Reset, wenn zwischendurch vom 
Programm das WDIE Bit nicht nochmal gesetzt wurde.

Diesen Fall habe ich noch nicht betrachtet; es könnte meine 
Schlußbemerkung zum Umkonfigurieren im Artikel obsolet machen bzw. die 
Umkonfiguration wesentlich erleichtern.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erledigt, Artikel ist umgeschrieben für den Modus Interrupt+System 
Reset.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi :)

Kannst du vllt mal kurz drüberschauen, wenn du Zeit hast? Ist nun eine 
etwas umgeschriebene Funktion, aber LED leuchtet immer noch nicht und er 
scheint auch nicht schlafen zu gehen ;(

Vllt weißt du wo der Fehler liegt...
int main(void)

{
  WDTCSR |= 0x48;      // setzt WDIE und WDE für Interrupt and System Reset Mode

  wdt_enable(WDTO_4S);  // Watchdog auf 4Sekunden bis zum Auslösen

  sei();          // Interrupts aktivieren
    
  while(1)
  
  {  
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_mode();       // in den Schlafmodus wechseln

    WDTCSR |= (1<<WDIE);// WDT Interrupt Flag erneut setzen, damit kein Reset erfolgt

    if (GO==1)
    
    {            
      SET_BIT(DDRB, DDB2);            
      CLR_BIT(PORTB, PB2);    // LED einschalten

      _delay_ms(1000);

      GO=0;
    }
  }      
}


//================================================================================================

//Watchdog Interrupt==============================================================================

ISR (WDT_vect)      // Interrupt Service Rountine Timer Overflow 2

{
  GO=1;
  SET_BIT(DDRB, DDB2);
  SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
}

Danke euch schonmal :)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.