Forum: Compiler & IDEs Watchdog First Time


von Alex (Gast)


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 :(
1
// Hauptprogramm===================================================================================
2
3
4
int main(void)
5
6
{
7
  //initLDR();              // LDR initialiseren
8
  
9
  //ACSR = 0x80;            // AD ausschalten
10
  
11
  wdt_enable(WDTO_8S);
12
13
  sei();                // Interrupts aktivieren
14
    
15
  while(1)
16
  
17
  {  
18
        wdt_reset();
19
    
20
    OCR2B = 0;                       // Dummyzugriff
21
        while((ASSR & (1<< OCR2BUB)));   // Warte auf das Ende des Zugriffs
22
 
23
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
24
        sleep_mode();                   // in den Schlafmodus wechseln
25
26
    if (GO==1)
27
    
28
    {            
29
      SET_BIT(DDRB, DDB2);            
30
      CLR_BIT(PORTB, PB2);    // LED einschalten, falls an
31
32
      _delay_ms(1000);
33
    }
34
  }      
35
}
36
37
38
//================================================================================================
39
40
//Watchdog Interrupt==============================================================================
41
42
ISR (WDT_vect)      // Interrupt Service Rountine Timer Overflow 2
43
44
{
45
  GO = 1;
46
  SET_BIT(DDRB, DDB2);
47
  SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
48
}


Danke euch schonmal!

von Stefan B. (stefan) Benutzerseite


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?).

von Alex (Gast)


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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Für den Atmega8 habe ich gerade ein kleines Beispiel dazu geschrieben.
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Pennen_bis_der_Hund_bellt

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

von Alex (Gast)


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?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Schau ich nach. Ich habe wohl noch einen Bug drin!

von Alex (Gast)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


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?

von Alex (Gast)


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?

von Stefan B. (stefan) Benutzerseite


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.

von Stefan B. (stefan) Benutzerseite


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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Erledigt, Artikel ist umgeschrieben für den Modus Interrupt+System 
Reset.

von Alex (Gast)


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...
1
int main(void)
2
3
{
4
  WDTCSR |= 0x48;      // setzt WDIE und WDE für Interrupt and System Reset Mode
5
6
  wdt_enable(WDTO_4S);  // Watchdog auf 4Sekunden bis zum Auslösen
7
8
  sei();          // Interrupts aktivieren
9
    
10
  while(1)
11
  
12
  {  
13
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
14
        sleep_mode();       // in den Schlafmodus wechseln
15
16
    WDTCSR |= (1<<WDIE);// WDT Interrupt Flag erneut setzen, damit kein Reset erfolgt
17
18
    if (GO==1)
19
    
20
    {            
21
      SET_BIT(DDRB, DDB2);            
22
      CLR_BIT(PORTB, PB2);    // LED einschalten
23
24
      _delay_ms(1000);
25
26
      GO=0;
27
    }
28
  }      
29
}
30
31
32
//================================================================================================
33
34
//Watchdog Interrupt==============================================================================
35
36
ISR (WDT_vect)      // Interrupt Service Rountine Timer Overflow 2
37
38
{
39
  GO=1;
40
  SET_BIT(DDRB, DDB2);
41
  SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
42
}

Danke euch schonmal :)

von Stefan B. (stefan) Benutzerseite


Lesenswert?


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.