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.
Setzt C das WDIE? Vielleicht mal den Watchdog-Interrupt programmieren, schaden kann's 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.
> Ich habe den Code nun wie folgt reduziert:
Der gegebene Code compiliert so nicht. Was hast Du denn sonst noch so
alles ausser main()?
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:
1 | #include <avr/io.h> |
2 | #include <avr/wdt.h> |
:
Bearbeitet durch User
Vollständigkeitshalber hier nochmal der an den bisherigen Kommentaren verbesserte, nicht funktionierende Code: #include <avr/io.h> #include <avr/wdt.h> 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); }
Ist der Watchdog per Fuse eingeschaltet? Dann lässt er sich nämlich überhaupt nicht abschalten.
Versuch mal ohne den wdh.h auf manuellen weg.
1 | //einschalten
|
2 | MCUSR = (1<<WDRF); |
3 | WDTCSR = (1<<WDE); // keine Prescale 16ms |
4 | |
5 | //ausschalten
|
6 | MCUSR = 0; |
7 | WDTCSR = 0; |
Datenblatt s.53 es gibt keine 15ms. Dann die Fuse WDTON keinen Haken setzen.
Steffen schrieb: > Datenblatt s.53 es gibt keine 15ms. 15ms = 16ms. So arg genau ist der sowieso nicht.
int main() { //wdt_disable(); //ausschalten MCUSR = 0; WDTCSR = 0; DDRD|=(1<<PD7); PORTD&= ~(1<<PD7); _delay_ms(1000); PORTD |= (1<<PD7); _delay_ms(1000); //wdt_enable(WDTO_500MS); //einschalten MCUSR = (1<<WDRF); WDTCSR = (1<<WDE); // keine Prescale 16ms while(1); } Keine Besserung. WDTON Fuse wird vom AVR Studio 5 Programmer als 0 gelesen.
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.
g457 schrieb: >> WDTON Fuse wird vom AVR Studio 5 Programmer als 0 gelesen. > > ..also an :-) genau...also wenn das die Ursache ist... mann mann mann
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
Ich habe das löschen von WDRF von ganz an den Anfang geschrieben, keine Änderung.
Jabu schrieb: > Ich habe das löschen von WDRF von ganz an den Anfang geschrieben, keine > Änderung. Und die Fuse?
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: > Fuse habe ich als 0 und auch als 1 getestet. IMHO muß man nach dem 1 setzen erstmal ausschalten, damit die Fuse auch übernommen wird.
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.
Tut mir leid für den Tippfehler mit dem "=" ! Die delay routine funktioniert dennoch problemlos! Habe dies jetzt korrigiert.
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
Habe nach der Programmierung der Fuse bits jeweils einen kompletten Reset = Spannung weg vorgenommen.
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...
Hast do einen Bootloader am laufen? Falls ja wirf den mal raus. Und: Pack das wdt_disable() mal in die .noinit [0] - main() ist regelmäßig zu spät. [0] http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html
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 /-:
> Sry, wo soll ich das wdt_disable() reinschreiben?
Auf den angegebenen Link klicken und lesen.
1 | #ifndef F_CPU
|
2 | #error F_CPU not defined.
|
3 | #endif
|
4 | |
5 | #include <avr/io.h> |
6 | #include <avr/wdt.h> |
7 | #include <util\delay.h> |
8 | |
9 | int main(void) |
10 | {
|
11 | MCUSR &= ~(1<<WDRF); |
12 | wdt_disable(); |
13 | |
14 | DDRD |= (1 << 7); |
15 | |
16 | for(unsigned char nInd = 0; nInd < 20; nInd++) |
17 | {
|
18 | PIND |= (1 << 7); |
19 | _delay_ms(50); |
20 | }
|
21 | |
22 | wdt_enable(WDTO_1S); |
23 | |
24 | while(1) |
25 | {
|
26 | PORTD &= ~(1 << 7); |
27 | }
|
28 | }
|
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: > Was machst du da mit PIND? Schnell blinken. Eine 1 schreiben nach PINx toggelt den Pin.
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.
:
Bearbeitet durch User
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?
1 | while(1) {} |
>> Letzter Stand des Programms: >> while(1); > > Sollte das nicht so aussehen? > > while(1) {} das ist semantisch äquivalent.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.