Problem mit Watchdog Interrupt initialisierung

Gast #4056700
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:
1
  if(MCUSR & _BV(WDRF)){            
2
    MCUSR &= ~_BV(WDRF);                     WDTCSR |= (_BV(WDCE) | _BV(WDE));   
3
    WDTCSR = 0x00;                      
4
  }

direkt danach:
1
  cli();
2
  WDTCSR |= (1<<WDCE)|(1<<WDE);        
3
  WDTCSR = (1<<WDIE)|(1<<WDP2)|(1<<WDP1)|(1<<WDP0);    
4
  //WDTCSR |= 0b01011111;
5
  //WDTCSR |= 0b00010111;
6
  //WDTCSR &= 0b11100111;
7
  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.
#4058264
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.
Gast #4058289
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.
#4058324
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.
Gast #4058339
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?
#4058522
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.
#4058556
Lesenswert?

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

Eher so:
1
  
2
WDTCSR |= (1<<WDE)|(1<<WDCE); // WDE und WDCE setzen
3
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
#4058567
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!
#4058599
Lesenswert?

1
#include <avr/wdt.h>
2

3

4
#ifdef WDTO_15MS
5
  #undef WDTO_15MS
6
#endif
7

8
#ifdef WDTO_30MS
9
  #undef WDTO_30MS
10
#endif
11

12
#ifdef WDTO_60MS
13
  #undef WDTO_60MS
14
#endif
15

16
#ifdef WDTO_120MS
17
  #undef WDTO_120MS
18
#endif
19

20
#ifdef WDTO_250MS
21
  #undef WDTO_250MS
22
#endif
23

24
#ifdef WDTO_500MS
25
  #undef WDTO_500MS
26
#endif
27

28
#ifdef WDTO_1S
29
  #undef WDTO_1S
30
#endif
31
#ifdef WDTO_2S
32
  #undef WDTO_2S
33
#endif
34
#ifdef WDTO_4S
35
  #undef WDTO_4S
36
#endif
37
#ifdef WDTO_8S
38
  #undef WDTO_8S
39
#endif
40

41
#define WDTO_16MS WDTO_15MS
42

43
#define WDTO_15MS   0
44
#define WDTO_30MS   (1 << WDP0)
45
#define WDTO_32MS   (1 << WDP0)
46
#define WDTO_60MS   (1 << WDP1)
47
#define WDTO_64MS   (1 << WDP1)
48
#define WDTO_120MS  ((1 << WDP1) | (1 << WDP0))
49
#define WDTO_125MS  ((1 << WDP1) | (1 << WDP0))
50
#define WDTO_250MS  (1 << WDP2)
51
#define WDTO_500MS  ((1 << WDP2) | (1 << WDP0))
52
#define WDTO_1S     ((1 << WDP2) | (1 << WDP1))
53
#define WDTO_2S     ((1 << WDP2) | (1 << WDP1) | (1 << WDP0))
54
#define WDTO_4S     (1 << WDP3)
55
#define WDTO_8S     ((1 << WDP3) | (1 << WDP0))
56

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

59
#ifdef WDTCR
60
  #define WDTCSR WDTCR
61
#endif
62

63
#ifdef WDTIE
64
  #define WDIE WDTIE
65
  #define WDIF WDTIF
66
#endif
67

68
#define WATCHDOG_RESET  1
69
#define WATCHDOG_TIMER  2
70

71

72
#define InitWdtTimer(mode, wdttime) do\
73
{\
74
  if(mode == WATCHDOG_RESET)\
75
  {\
76
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
77
    MCUSR &= ~(1 << WDRF);\
78
    unsigned char temp = (1 << WDE) | wdttime;\
79
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
80
    WDTCSR = temp;\
81
  }\
82
  if(mode == WATCHDOG_TIMER)\
83
  {\
84
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
85
    MCUSR &= ~(1 << WDRF);\
86
    unsigned char temp = (1 << WDIE) | wdttime;\
87
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
88
    WDTCSR = temp;\
89
  }\
90
  if(mode == WATCHDOG_RESET + WATCHDOG_TIMER)\
91
  {\
92
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
93
    MCUSR &= ~(1 << WDRF);\
94
    unsigned char temp = (1 << WDE) | (1 << WDIE) | wdttime;\
95
    WDTCSR |= (1 << WDCE) | (1 << WDE);\
96
    WDTCSR = temp;\
97
  }\
98
}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.
Gast #4059711
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...
Gast #4059750
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 |= ...
Gast #4059764
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) :/
#4067950
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren