Hey,
Ich habe ein Problem mit dem Watchdog Reset des ATmega644. Ich möchte an
einer beliebigen Programmstelle einen Reset des AVRs bewirken und nutze
dafür den WDT. Das sieht recht simpel aus:
wdt_enable(WDTO_15MS);
while(1); //Reset sollte nach 15ms erfolgen
Das tut er dann auch. Neu starten tut er dann allerdings nicht mehr,
selbst wenn ich ganz am Beginn der main()
wdt_disable();
einfüge. Vielleicht sollte ich diesen Fehler etwas erklären: Es scheint
schon ein Start durchgeführt zu werden, das Backlight vom LCD welches in
ansteuere fängt wie wild an zu flackern (sollte eigentlich einfach nur
eingeschaltet werden) und das wars dann auch schon. Dieser Zustand
bleibt erhalten, von einem normalen Programmstart nicht zu reden. Selbst
bei manuelem Reset wird nach auftreten dieses Fehlers das Programm nicht
mehr richtig gestartet. Erst nachdem VCC einige Sekunden weg ist und
dann wieder angelegt wird startet das Programm ordnungsgemäß.
Hat jemand eine Idee?
Das ist weder witzig noch bringt es irgendjemanden weiter. Ich kann den
Code hier gerne posten aber aus viel mehr als den 3 Zeilen und der LCD
Initialisierung, die einwandfrei funktioniert, besteht der nunmal nicht.
Ich habe den Code nun wie folgt reduziert:
int main()
{
wdt_disable();
DDRD|=(1<<PD7);
PORTD&= ~(1<<PD7);
_delay_ms(1000);
PORTD |= (1<<PD7);
_delay_ms(1000);
wdt_enable(WDTO_15MS);
while(1);
}
Hiernach sollte die am PD7 angeschlossene LED mit ca. 1Hz blinken, das
tut sie allerdings nicht. main() wird nur einmal korrekt ausgeführt,
danach bleibt die LED aus.
Jabu schrieb:> Ich habe den Code nun wie folgt reduziert:>> int main()> {> wdt_disable();> DDRD|=(1<<PD7);>> PORTD&= ~(1<<PD7);> _delay_ms(1000);> PORTD |= (1<<PD7);> _delay_ms(1000);> wdt_enable(WDTO_15MS);> while(1);> }>> Hiernach sollte die am PD7 angeschlossene LED mit ca. 1Hz blinken, das> tut sie allerdings nicht. main() wird nur einmal korrekt ausgeführt,> danach bleibt die LED aus.
Aus dem Tutorial:
Bei neueren AVR-Typen bleibt der Watchdog auch nach einem Reset durch
den Watchdog aktiviert. Wenn ein Programm nach dem Neustart bis zur
erstmaligen Rückstellung des Watchdogs länger braucht, als die im
Watchdog eingestellte Zeit, sollte man den Watchdog explizit möglichst
früh deaktivieren. Ansonsten resetet der Watchdog den Controller
immerfort von Neuem. Die frühe Deaktivierung sollte durch eine Funktion
erfolgen, die noch vor allen anderen Operationen (insbesondere vor dem
mglw. länger andauernden internen Initialisierungen vor dem Sprung zu
main()) ausgeführt wird. Näheres zur Implementierung mit
avr-gcc/avr-libc findet sich in der Dokumentation der avr-libc
(Suchbegriffe: attribut, section, init).
Versuch mal die Zeit hoch zu stellen.
Bei mir kompiliert dieser Code wunderbar, ich habe alle anderen
Programmteile bis auf dieses main rausgenommen. Auch habe ich nun die
WDT Zeit auf 500ms hochgesetzt, ohne Unterschied. Auch MCUSR = 0; folgt
jetzt gleich auf wdt_disable, ohne Änderung.
g457 schrieb:> Der gegebene Code compiliert so nicht. Was hast Du denn sonst noch so> alles ausser main()?
Wahrscheinlich das hier am Anfang der Datei:
Oliver schrub:
> Wahrscheinlich das hier am Anfang der Datei:
Es ist uninteressant was es ∗wahrscheinlich∗ ∗ungefähr∗ ist - der TO
soll mit seinem ∗echten∗ Code rausrücken, sonst ist das nur Fischen im
Nebel.
Zum echten Code zählt alles, nicht nur etwas das ungefähr ein bisschen
fast so ähnlich aussieht.
A. K. schrieb:> Steffen schrieb:>> Versuch mal ohne den wdh.h auf manuellen weg.>> Ohne WDCE?
naja muss man testen.
Aus dem Datenblatt:
> This bit is used in timed sequences for changing WDE and prescaler bits. > To
clear the WDE bit,
> and/or change the prescaler bits, WDCE must be set.
prescaler wird ja nicht gesetzt.
Steffen schrieb:> naja muss man testen.
Ist eindeutig. Um WDE zurückzusetzen muss WDCE gesetzt sein. Hat ja auch
einen Sinn, das soll nicht aus versehen geschehen dürfen.
Er soll mal ruhig beim wdt_reset() bleiben.
Um sämtliche fehlerhaften Einflüsse auszuschließen habe ich ein neues
Projekt angelegt in dem nichts weiter als folgendes steht:
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#define F_CPU = 8000000
int main()
{
wdt_disable();
MCUSR = 0; //Nachgebessert (Interrupt Flag Reset)
DDRD|=(1<<PD7);
PORTD&= ~(1<<PD7);
_delay_ms(1000);
PORTD |= (1<<PD7);
_delay_ms(1000);
wdt_enable(WDTO_500MS); //Nachgebessert auf 500ms
while(1);
}
WDTON Fuse habe ich testweise auf 1 gesetzt, die LED bleibt dan
dauerhaft aus. Wenn diese auf 0 ist geht sie wie vorher bereits nur
einmal an.
Jabu schrieb:> wdt_disable();> MCUSR = 0; //Nachgebessert (Interrupt Flag Reset)
Immer noch falsch rum. Solange WDRF an ist geht der Wachdog nicht aus.
A. K. schrieb:> Steffen schrieb:>> naja muss man testen.>> Ist eindeutig. Um WDE zurückzusetzen muss WDCE gesetzt sein. Hat ja auch> einen Sinn, das soll nicht aus versehen geschehen dürfen.>> Er soll mal ruhig beim wdt_reset() bleiben.
Naja sollte ja ein Test sein ob es vielleicht an der wdt.h liegt. So
weit wie ich das gelesen habe macht er keinen wdt_reset irgendwie... tut
ja auch sonst wie Geheimsnissvoll um den Quelltext. Nuja jetzt sind wir
bei der Minimalanforderung und beim Lernen wie der WDT funktioniert
angekommen :-D
Fuse habe ich als 0 und auch als 1 getestet. Als 0 leuchtet die LED
einmal auf, als 1 bleibt alles dunkel.
@ Steffen:
Ich möchte auch keinen wdt_reset() machen, ich möchte den AVR
softwareseitig zum reset zwingen und das funktioniert nach meinem Wissen
nur über den WDT Reset. Wen du eine bessere Methode kennst bitte teile
sie mir mit.
Jabu schrieb:> #include <avr/delay.h>>> #define F_CPU = 8000000
Erstens heisst das
#define F_CPU 8000000
Zweitens hast du den Stall zugesperrt, nachdem das Pferd schon ausgebüxt
ist. Denn F_CPU wird von delay.h benötigt.
Jabu schrieb:> Fuse habe ich als 0 und auch als 1 getestet. Als 0 leuchtet die LED> einmal auf, als 1 bleibt alles dunkel.>> @ Steffen:> Ich möchte auch keinen wdt_reset() machen, ich möchte den AVR> softwareseitig zum reset zwingen und das funktioniert nach meinem Wissen> nur über den WDT Reset. Wen du eine bessere Methode kennst bitte teile> sie mir mit.
Aach ja....
Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das
so schnell das man das nicht sieht. Stell mal den WDT auf 1s
Steffen schrieb:> Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das> so schnell das man das nicht sieht. Stell mal den WDT auf 1s
Du hängst etwas. Er steht schon bei 500ms. Ausserdem ist für die Dauer
der LED das Delay zuständig.
Jabu schrieb:> Tut mir leid für den Tippfehler mit dem "=" ! Die delay routine> funktioniert dennoch problemlos! Habe dies jetzt korrigiert.
Die tut auch ganz ohne F_CPU. Nur nicht unbedingt mit der gewünschten
Zeit.
Letzter Stand des Programms:
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#define F_CPU 8000000
int main()
{
MCUSR = 0;
wdt_disable();
DDRD|=(1<<PD7);
PORTD&= ~(1<<PD7);
_delay_ms(1000);
PORTD |= (1<<PD7);
_delay_ms(1000);
wdt_enable(WDTO_500MS);
while(1);
}
Getestet mit WDTON Fuse 0/1 (Wobei Haken raus die korrekte Belegung zu
sein scheint, bezogen auf AVRStudio 5.0 ISP Programmer), VCC jeweils
mehrere Sekunden weggenommen nach programmieren von den Fuses, Problem
besteht weiterhin.
Danke für die große Resonanz und die viele Vorschläge, hier nurmal kurz
eingeschoben.
A. K. schrieb:> Steffen schrieb:>> Die LED kann ja nicht an gehn, nach 16ms kommt der Reset die macht das>> so schnell das man das nicht sieht. Stell mal den WDT auf 1s>> Du hängst etwas. Er steht schon bei 500ms. Ausserdem ist für die Dauer> der LED das Delay zuständig.
ja das simmt, der Tatort lenkt mich ab. Also ich würder bei der
manuellen WDT Routine bleiben und am Anfang alles ausschalten. Dann das
Programm laufen lassen und dann den Reset Starten. Das muss gehen.
Wichtig die Fuse auf 1
Jabu schrieb:> Wenn ich ein Haken in WDTON setze ist die LED nach wie vor dauerhaft> aus.
also eins fällt mir noch ein, Programmer abgesteckt?, JTAG Debugger
abgesteckt?
Habe den ISP Stecker jeweils abgezogen. Das einzige was ich mir hierzu
noch vorstellen kann ist, dass es sich um irgendeinen Hardwarefehler
handelt, auch wenn ich diesen Controller in seiner Umgebung schon Wochen
problemlos programmiere. Ich werde morgen mal ein anderes Board
ausprobieren, vielleicht ergibt sich da was.
Jabu schrieb:> Habe den ISP Stecker jeweils abgezogen. Das einzige was ich mir hierzu> noch vorstellen kann ist, dass es sich um irgendeinen Hardwarefehler> handelt, auch wenn ich diesen Controller in seiner Umgebung schon Wochen> problemlos programmiere. Ich werde morgen mal ein anderes Board> ausprobieren, vielleicht ergibt sich da was.
Naja oder das Programm (diesen Testcode) in einem komplett neuen Project
erstellen.
Jetzt tun Sie mir doch den Gefallen und belegen, wie schon vor
anderthalb Stunden vorgeschlagen, und auch nur als Schuss ins Blaue
hinein, den Watchdog-Interrupt, wie auch immer das in C aussieht.
Dann kann ich nämlich endlich zu Bett gehen, die Nachtschwester meckert
schon.
Wie der in C aussieht weiß ich leider genauso wenig und bevor ich da
jetzt etwas hinklatsche werde ich das lieber die tage mal ausprobieren,
Dennoch danke für die Idee. Wundern tut es mich trotzdem warum es nicht
ohne zu gehen scheint...
Verwende keinen Bootloader. Sry, wo soll ich das wdt_disable()
reinschreiben? s/.noinit/.init3/g; sagt mir nichts.
Tut mir leid wenn diese frage unnötig unwissend ist /-:
Led blinkt 1s, leuchtet 1s, Watchdog schlägt zu, Spiel beginnt von vorn.
Ist die Watchdog-Fuse gesetzt, schlägt der Watchdog 16ms nach Reset zu,
löst einen Reset aus... Die LED blinkt heftig.
Wenn das nicht so ist, ist deine Schaltung im A..., der Controller
kaputt oder irgend jemand zu doof für diese Welt.
mfg.
Was machst du da mit PIND? Und warum läuft die for-Schleife um 20 mal
eine Warteschaleife aufzurufen? Wie kommt es dass du PORTD &= ~(1 << 7)
wieder und wieder in der while-schleife auf 0 setzt?
Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie
mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR
getestet?
Jabu schrieb:> Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie> mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR> getestet?
Gibts irgendwelche Fehler oder Warnungen, die "völlig unwichtig" sind?
Es ist auch garantiert der richtige Controller und die Hardware hat
alles, was das hiesige Tutorial empfiehlt?
Soll heissen: Mach mal ein Bild vom Aufbau.
Jabu schrieb:> Was machst du da mit PIND?
Toggeln.
> Und warum läuft die for-Schleife um 20 mal eine Warteschaleife> aufzurufen?
Damit es 20 Mal blinkt.
> Wie kommt es dass du PORTD &= ~(1 << 7)> wieder und wieder in der while-schleife auf 0 setzt?
Das PORTD &= ~(1 << 7) kann auch vor der while-Schleife stehen. Aber dem
Controller ist das sowas von egal...
> Ich habe das Programm so aufgespielt und es zeigt sich das gleiche wie> mit dem anderen. Kein blinken. Hast du das Programm auf einem AVR> getestet?
Ja.
Übliche Fehler:
CKDIV8-Fuse gesetzt?
Falsches Hex-File geflasht?
Ich mache alles richtig!
Aber dann würde es laufen.
mfg.
Das Problem hat sich gelöst. Es hatte tatsächlich mit dem programmieren
der FUSE bits zu tun, diese Programmierung wurde wohl nicht korrekt
ausgeführt und eine unscheinbare Fehlermeldung ist erschienen.
Danke nochmal für die Hilfe.
Jabu schrieb:> Das Problem hat sich gelöst. Es hatte tatsächlich mit dem programmieren> der FUSE bits zu tun, diese Programmierung wurde wohl nicht korrekt> ausgeführt und eine unscheinbare Fehlermeldung ist erschienen.>> Danke nochmal für die Hilfe.
Das ist nicht dein Ernst.
A. K. schrieb:> Naja, glauben wir das mal... ;-)
Ich nicht so wirklich.
Mir ist da glaub ich noch n Fehler aufgefallen mit der while(1);
Jabu schrieb:> Letzter Stand des Programms:> while(1);
Sollte das nicht so aussehen?
Steffen schrieb:>> Naja, glauben wir das mal... ;-)>> Ich nicht so wirklich.
Ich ja auch nicht. Ich vermute, dass er seit Stunden das immer gleiche
alte Hexfile reinjagte. Und sich nicht traut, das zuzugeben.
> while(1) {}
Ist egal.