Forum: Mikrocontroller und Digitale Elektronik Watchdog- wie realisiere ich einen Reset?


von uC-Anfänger (Gast)


Lesenswert?

Hallo zusammen, ich bin Neuling auf dem Gebit uC-Programmierung und 
möchte gerne beim auftreten eines bestimmten Zustandes in meinem 
Programm, einen Reset auslösen. Ich programmiere einen ATmega2560 in C.

Nun habe ich gelesen das hierbei der Watchdog mir Abhilfe schaffen kann. 
Im Tutorial habe ich gelesen, dass ich zunächst die #include <avr/wdt.h> 
einfügen muss.

Gut, aber wie muss ich jetzt weitermachen?

void wdt_init(void)
{
    MCUSR = 0;
    wdt_disable();

    return;
}

kann ich dann einfach beim Auftreten von error wdt_reset() schalten und 
mein Programm resetet?

if( error == 1 )
{
wdt_reset();
}

würde das so passen ich check das irgenwie immer noch nicht so ganz mit 
der Watchdog-Geschichte.

Das geliche ist, wenn ich auf ein Flag warten will und das wird 
innerhalb einer bestimmten Zeit nicht gesetzt, wie muss ich da vorgehen? 
Bin über jede Hilfe glücklich.

von Thomas E. (thomase)


Lesenswert?

uC-Anfänger schrieb:
> void wdt_init(void)
> {
>     MCUSR = 0;
>     wdt_disable();
>     return;
> }
> kann ich dann einfach beim Auftreten von error wdt_reset() schalten und
> mein Programm resetet?
> if( error == 1 )
> {
>   wdt_reset();
> }

> würde das so passen ich check das irgenwie immer noch nicht so ganz mit
> der Watchdog-Geschichte.

Nein.

Sinn und Zweck eines Watchdog ist es, den Controller zu resetten, wenn 
sich das Programm an irgendeiner Stelle aufgehängt hat. Man kann den 
Watchdog natürlich auch zum gezielten Resetten benutzen, indem man 
diesen Zustand herbeiführt.

Erstmal wird der Watchdog gestartet:  wdt_enable(value)
"value" ist ein Wert für die Zeit, genaugenommen wird damit der 
Prescaler eingestellt, nach der ein Reset durchgeführt wird.

Damit startet man den  Watchdogtimer. Wenn dieser Timer überläuft, wird 
ein Reset ausgeführt. Damit das nicht passiert, gibt es die Funktion
"wdt_reset()". Damit wird der Zähler wieder auf 0 gesetzt.
Diese Funktion baut man nun an geeigneter Stelle im Programm ein, meist 
in der Hauptprogrammschleife. Kehrt das Programm jetzt beispielsweise 
nicht rechtzeitig aus einer Interruptbehandlung zurück, läuft der Zähler 
über und es gibt einen Reset.

Um einen gezielten Reset herbeizuführen, muß der WDT erstmal beim Start 
des Programms abgeschaltet werden: wdt_disable();

In der Funktion, die den Reset ausführen soll, startest du dann den 
Watchdog mit der kürzest möglichen Zeit: wdt_enable(0);
Das sind ungefähr 15 oder 16 ms, schneller geht nicht, und wartest auf 
den Reset: while(1){}

uC-Anfänger schrieb:
> Das geliche ist, wenn ich auf ein Flag warten will und das wird
> innerhalb einer bestimmten Zeit nicht gesetzt, wie muss ich da vorgehen?

Das machst du so ähnlich.
Du lässt einen Timer laufen, der nach der Time-Out-Zeit überläuft und 
einen Interrupt auslöst.

Den Timer startest du, wenn du auf das Flag wartest und stoppst ihn, 
nachdem du das Flag erhalten hast. Oder wenn du etwas über den UART 
gesendet hast und auf Antwort wartest.

Dauert es zulange, läuft der Timer über und löst einen Interrupt aus.

Für längere Zeiten oder wenn du den Timer auch noch für etwas anders 
nutzen willst, baut man eine oder mehrere Variablen ein und fragt die 
entsprechend ab.

mfg.

von Peter D. (peda)


Lesenswert?

uC-Anfänger schrieb:
> Das geliche ist, wenn ich auf ein Flag warten will und das wird
> innerhalb einer bestimmten Zeit nicht gesetzt, wie muss ich da vorgehen?

Das macht man nicht mit dem Watchdog, da dieser einen echten Reset 
auslöst. D.h. sämtliche gerade laufenden Tasks werden gekillt und das 
will man ja nicht.
Sieht auch äußerst unprofessionell aus, wenn LEDs und Displays flackern, 
Relais klappern, Motoren stottern, Einstellungen vergessen werden usw.

Man setzt daher einen Timeout-Handler auf. Ein Timerinterrupt prüft, ob 
eine bestimmte Zeit vergangen ist und ruft diesen dann auf.
Erfolgt das gewünschte Ereignis rechtzeitig, wird der Timeout-Handler 
wieder gestoppt (Zeitvariable = 0).


Peter

von uC-Anfänger (Gast)


Lesenswert?

Hallo zusammen,
Danke für die Antworten. Wenn ich einen ERROR detektiere, möchte ich 
aber einen Reset auslösen. Da eignet sich der Watchdog ja soweit dafür.

Also im Grunde muss ich ja nur die Header <avr/wdt.h> einbauen und bei

if( error == 1 )
wdt_enable(0);

setzen, oder? Aber ich muss den doch auch irgendwie initialisieren. Muss 
ich zu Beginn des Programmes, in meiner main, den Watchdog erst 
deaktivieren?
Wäre nett wenn mir hierzu vielleicht jemand nochmals helfen könnte.

VG

von Thomas E. (thomase)


Lesenswert?

uC-Anfänger schrieb:
> Muss ich zu Beginn des Programmes, in meiner main, den Watchdog erst
> deaktivieren?

Beim ersten Mal nicht.

Aber nach einem Watchdog-Reset bleibt der Watchdog eingeschaltet. Und 
würde sonst sofort wieder nach Ablauf der Verzögerung resetten.

mfg.

von uC-Anfänger (Gast)


Lesenswert?

OK

zusammenfassend also:

- <avr/wdt.h> einbinden

- wdt_disable() in main setzen

- dann in meine main-loop

- if(error == 1)
 wdt_enable(0);

--> reset!!!

--> wdt_disable()

--> ab in die main-loop und weiter gehts

von Thomas E. (thomase)


Lesenswert?

uC-Anfänger schrieb:
> - wdt_disable() in main setzen

Gleich als erstes in main. Und gut.

mfg.

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.