Datum:
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!
Datum:
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?).
Datum:
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
Datum:
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
Datum:
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?
Datum:
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?
Datum:
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?
Datum:
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.
Datum:
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.
Datum:
Erledigt, Artikel ist umgeschrieben für den Modus Interrupt+System Reset.
Datum:
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 :)