Forum: Compiler & IDEs Problem mit Watchdog Interrupt initialisierung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich bin seit gestern daran zu verzweifeln meinen Watchdog in den 
Interrupt Modus zu bringen. aktuell habe ich folgenden Code:

am Anfang des Programms:
  if(MCUSR & _BV(WDRF)){            
    MCUSR &= ~_BV(WDRF);                     WDTCSR |= (_BV(WDCE) | _BV(WDE));   
    WDTCSR = 0x00;                      
  }

direkt danach:
  cli();
  WDTCSR |= (1<<WDCE)|(1<<WDE);        
  WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);    
  //WDTCSR |= 0b01011111;
  //WDTCSR |= 0b00010111;
  //WDTCSR &= 0b11100111;
  sei();

In der Routine selbst mache ich nichts außer einer Uart ausgabe.

ich habe im Debugger die einzelnen Bits verfolgt, und es wird nie die 
Zeit eingestellt bzw das WDE Bit gelöscht! Im Debugging selber kann ich 
händisch über die Oberfläche die Bits setzen und der Interrupt 
funktioniert ohne Probleme. Habt ihr eine Idee woran es liegen könnte?

Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
keiner eine Idee?

von Ingo L. (corrtexx)


Bewertung
-1 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4056700:
> WDTCSR |= (1<<WDCE)|(1<<WDE);
>   WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
Was soll das auch? Du aktivierst den WDT in der ersten Zeile und löscht 
ihn sofort in der zweiten Zeile!

AVR-Anfänger schrieb im Beitrag #4056700:
> Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.
Du musst auch das WDTON-Fuse setzen soweit ich mich erinnere.

Mach mal bitte ne genauere Erklärung was du willst und was du hast.

: Bearbeitet durch User
von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ingo Less schrieb:
> AVR-Anfänger schrieb im Beitrag #4056700:
>> WDTCSR |= (1<<WDCE)|(1<<WDE);
>>   WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);
> Was soll das auch? Du aktivierst den WDT in der ersten Zeile und löscht
> ihn sofort in der zweiten Zeile!
>

das wird im Datenblatt so vorgeschrieben, um den Watchdog nicht 
ausversehen zu konfigurieren. Ich habe es jedenfalls so verstanden....

> AVR-Anfänger schrieb im Beitrag #4056700:
>> Das Fusebit WDTON ist nicht gesetzt und ich verwende einen ATmega2560.
> Du musst auch das WDTON-Fuse setzen soweit ich mich erinnere.
>
Mit dem WDTON Bit wird der Watchdog Hartdwaremäßig im Reset Modus 
gehalten oder?

> Mach mal bitte ne genauere Erklärung was du willst und was du hast.

Ich möchte den Watchdog im Interruptmodus nutzen, um das Aufhängen des 
Programmes zu verhindern, beispielsweise wenn ein Sensor nicht reagiert.

von Ingo L. (corrtexx)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058289:
> Ich möchte den Watchdog im Interruptmodus nutzen, um das Aufhängen des
> Programmes zu verhindern
Wie denn genau? Mir scheint fast du steuerst auf eine falsche Lösung 
drauf zu. Aber ohne eine genauere Beschreibung oder mal den Code kann 
man dir nicht helfen. Ich habe nämlich immernoch nicht ganz begriffen 
was du eigentlich machen willst.

von Oliver S. (oliverso)


Bewertung
1 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058289:
> das wird im Datenblatt so vorgeschrieben, um den Watchdog nicht
> ausversehen zu konfigurieren. Ich habe es jedenfalls so verstanden....

WDE muß in beiden Schritten gesetzt sein. Nur WDCE ist einmal 1 und 
einmal 0.

Oliver

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Beispielsweise um die Kommunikation zwischen zwei Boards zu überwachen, 
als Timeout quasi. Antwortet das 2. Board innerhalb einer bestimmten 
Zeit nicht, soll der Watchdog auslösen.

ok soweit?

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Oliver, eher so:
  WDTCSR |= (1<<WDE)|(1<<WDCE);        
  WDTCSR = (1<<WDE)|(1<<WDCE)|(1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);    
  WDTCSR = (1<<WDCE)|(1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);   

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058339:
> Antwortet das 2. Board innerhalb einer bestimmten
> Zeit nicht

Dann setzt man eine Timeout-Handler auf, der von einem Timerinterrupt 
getriggert wird.

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Auch eine Möglichkeit, aber ich würde trotzdem gerne den Watchdog 
benutzen :/

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058452:
> aber ich würde trotzdem gerne den Watchdog
> benutzen :/

Dann mußt Du da durch.

Ich wollte Dir nur die übliche Methode aufzeigen. Einen Timer hat man ja 
eh oft laufen. Da ist es das einfachste, einen oder auch mehrere 
Timeouts mit reinzuhängen. Und man muß sich nicht mit Timed-Access und 
anderen Schnulli rumplagen und riskiert keinen versehentlichen Reset.

Vielleicht stehen ja in der wdt.h passende Macros.

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058350:
> @Oliver, eher so:
...

Eher so:
  
WDTCSR |= (1<<WDE)|(1<<WDCE); // WDE und WDCE setzen
WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0); // WDIE aktiviert Interrupt, WDCE muß 0 sein

Mit WDE lag ich falsch, das muß nur gesetzt bleiben, wenn man auch den 
WD-Reset aktivieren will. WDCE muß beim 2. Zugriff 0 sein.
Da du den Interrupt nutzen willst, muß auch WDIE gesetzt werden.

Oliver

von Ingo L. (corrtexx)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4058339:
> Beispielsweise um die Kommunikation zwischen zwei Boards zu überwachen,
> als Timeout quasi. Antwortet das 2. Board innerhalb einer bestimmten
> Zeit nicht, soll der Watchdog auslösen.
Ich glaube das ist die ungeschickteste Möglichkeit ein Timeout zu 
überwachen, ich würd es auch wie Peter machen. Das ist der richtige Weg, 
zumal man so ein Timeout deutlich präziser einstellen kann als mit dem 
doch recht groben Prescalern des WDT...

Aber, Oliver hat dir ja schon erzählt wie man den WDT einstellt, dann 
man los!

: Bearbeitet durch User
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
#include <avr/wdt.h>


#ifdef WDTO_15MS
  #undef WDTO_15MS
#endif

#ifdef WDTO_30MS
  #undef WDTO_30MS
#endif

#ifdef WDTO_60MS
  #undef WDTO_60MS
#endif

#ifdef WDTO_120MS
  #undef WDTO_120MS
#endif

#ifdef WDTO_250MS
  #undef WDTO_250MS
#endif

#ifdef WDTO_500MS
  #undef WDTO_500MS
#endif

#ifdef WDTO_1S
  #undef WDTO_1S
#endif
#ifdef WDTO_2S
  #undef WDTO_2S
#endif
#ifdef WDTO_4S
  #undef WDTO_4S
#endif
#ifdef WDTO_8S
  #undef WDTO_8S
#endif

#define WDTO_16MS WDTO_15MS

#define WDTO_15MS   0
#define WDTO_30MS   (1 << WDP0)
#define WDTO_32MS   (1 << WDP0)
#define WDTO_60MS   (1 << WDP1)
#define WDTO_64MS   (1 << WDP1)
#define WDTO_120MS  ((1 << WDP1) | (1 << WDP0))
#define WDTO_125MS  ((1 << WDP1) | (1 << WDP0))
#define WDTO_250MS  (1 << WDP2)
#define WDTO_500MS  ((1 << WDP2) | (1 << WDP0))
#define WDTO_1S     ((1 << WDP2) | (1 << WDP1))
#define WDTO_2S     ((1 << WDP2) | (1 << WDP1) | (1 << WDP0))
#define WDTO_4S     (1 << WDP3)
#define WDTO_8S     ((1 << WDP3) | (1 << WDP0))

#define WDP_ALL  ((1 << WDP3) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0))

#ifdef WDTCR
  #define WDTCSR WDTCR
#endif

#ifdef WDTIE
  #define WDIE WDTIE
  #define WDIF WDTIF
#endif

#define WATCHDOG_RESET  1
#define WATCHDOG_TIMER  2


#define InitWdtTimer(mode, wdttime) do\
{\
  if(mode == WATCHDOG_RESET)\
  {\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    MCUSR &= ~(1 << WDRF);\
    unsigned char temp = (1 << WDE) | wdttime;\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    WDTCSR = temp;\
  }\
  if(mode == WATCHDOG_TIMER)\
  {\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    MCUSR &= ~(1 << WDRF);\
    unsigned char temp = (1 << WDIE) | wdttime;\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    WDTCSR = temp;\
  }\
  if(mode == WATCHDOG_RESET + WATCHDOG_TIMER)\
  {\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    MCUSR &= ~(1 << WDRF);\
    unsigned char temp = (1 << WDE) | (1 << WDIE) | wdttime;\
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
    WDTCSR = temp;\
  }\
}while(0


Bei einigen älteren AVRs geht es auch einfacher. Mit dieser Methode 
funktioniert es bei allen. Ergänzend zur wdt.h sind auch die längeren 
Timeouts enthalten, die der Atmega8 und die anderen Altlasten nicht 
kennen.

mfg.

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@ Thomas Eckmann,

ich habe gerade versucht deinen Code einzubinden und auszuprobieren, 
aber der Watchdog lässt sich immernoch nicht im Interrupt Modus 
aktivieren...ich wird noch verrückt...

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
Debbugst du einen realen AVR, oder den Simulator im Studio?

Oliver

von Amateur (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Eine Sequenz wie:
WDTCSR |= ...
WDTCSR  = ...
ist grundsätzlich Unsinn.

Denn egal was Du in der ersten Zeile auch machst, in der zweiten Zeile 
wird es überschrieben.

Wenn es schon zwei Zeilen sein müssen, dann aber
WDTCSR |= ...
WDTCSR |= ...

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Oliver: live im AVR

@ Amateur
Amateur schrieb:
> Eine Sequenz wie:
> WDTCSR |= ...
> WDTCSR  = ...
> ist grundsätzlich Unsinn.
>
> Denn egal was Du in der ersten Zeile auch machst, in der zweiten Zeile
> wird es überschrieben.
>
> Wenn es schon zwei Zeilen sein müssen, dann aber
> WDTCSR |= ...
> WDTCSR |= ...

so wird es aber im Datenblatt des AVR vorgezeigt(seite 66 ATmega2560) :/

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
Amateur schrieb:
> ist grundsätzlich Unsinn.

In dem Fall ist es genau richtig.
Datenblatt lesen oder Dieter Nuhr...

Oliver

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also das Problem scheint der ATmega2560 gewesen zu sein.. ich habe das 
ganze nochmal mit einem 644p versucht, da hat es wunderbar geklappt :/

von Oliver S. (oliverso)


Bewertung
0 lesenswert
nicht lesenswert
AVR-Anfänger schrieb im Beitrag #4067849:
> also das Problem scheint der ATmega2560 gewesen zu sein

Na, dann beschwer dich mal bei Atmel darüber, daß die M2560er mit 
defektem Watchdog ausliefern.


Oliver

von AVR-Anfänger (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mit der Vermutung da etwas Ironie heraus zu lesen will ich hinzufügen, 
dass das Board mit dem 2560 ein Bastelboard ist. Wer weiß wo der 
schonmal einen Schaden genommen hat..

von Uwe S. (de0508)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

es liegt sicherlich nicht am Watchdog, sondern am Programm.

Nur selten habe ich ml einen AVR µC Pin zerstören können.
Das ist aber dann meine Schuld und ich konnte es nachvollziehen.
Ein AVR µC wurde bei einem Selbstbauseminar mal mit 9V versorgt und 
hatte es überstanden, im Datenblatt ist zu lesen <7V an Vcc.

Die Inhalte aus den Atmel µC Datenblättern sind nicht immer einfach zu 
lesen, da manche Sachverhalte durch weitere Zeile im Datenblatt ergänzt 
bzw. eingschränkt werden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.