Forum: Mikrocontroller und Digitale Elektronik ATMega128 --> Watchdog Komisches Verhalten nach POR


von Detlev Neumann (Gast)


Lesenswert?

Hallo Zusammen,

ich habe zum Test folgenden code geschrieben Nach dem Einschalten der 
Versorgungsspannung durchläuft der Controller zweimal den Code obwohl 
ich
nach meinem dafür halten den Controller in der Endlosschleife festhalten 
müsste und das schon beim ersten mal. (Gemesse mit meinem Ozi am 
Port-Pin ).

Mache ich was falsch übersehe ich was??
1
#define wdt_reset()  asm("wdr")
2
3
4
void enable_Watchdog(void)
5
{
6
  //Watchdog
7
   WDTCR &= ~( (1<<WDCE);
8
   WDTCR |=  ( 1 << WDE)|(1 << WDP2)| (1 << WDP1) | (1 << WDP0);
9
   NOP();
10
   NOP();
11
   NOP();
12
   wdt_reset();
13
 }
14
15
void main(void)
16
{
17
  unsigned int c;  
18
 
19
  init();  //initialisiert Port-Pins
20
  enable_Watchdog();
21
  PORTB &=~0x40; 
22
  c=50;
23
  do{c--;} while(c);
24
  PORTB |= 0x80;
25
  do{c--;} while(c);
26
  PORTB &=~0x40; 
27
28
  do{wdt_reset();} while(1);
29
}

Danke

Detlev

P.S. ich verwende den IAR - Compiler

von Pothead (Gast)


Lesenswert?

Versuchs mal hiermit. Denke aber, dass das Problem woanders liegt. Was 
passiert wenn du den WDT nicht aktivierst?
1
#define wdt_reset()  asm("wdr")
2
3
4
void enable_Watchdog(void)
5
{
6
  //Watchdog
7
   WDTCR &= ~( (1<<WDCE);
8
   WDTCR |=  ( 1 << WDE)|(1 << WDP2)| (1 << WDP1) | (1 << WDP0);
9
   NOP();
10
   NOP();
11
   NOP();
12
   wdt_reset();
13
 }
14
15
void main(void)
16
{
17
  unsigned int c;  
18
 
19
  init();  //initialisiert Port-Pins
20
21
  enable_Watchdog();
22
23
  PORTB &=~0x40;
24
25
  c=50;
26
27
  do
28
  {
29
    c--;
30
    wdt_reset();
31
  } 
32
  while(c);
33
34
  PORTB |= 0x80;
35
36
  do
37
  {
38
    c--;
39
    wdt_reset();
40
  }
41
  while(c);
42
43
  PORTB &=~0x40; 
44
45
  do{wdt_reset();} while(1);
46
}

von ... (Gast)


Lesenswert?

Also, wenn der Compiler auch nur halbwegs diesen Namen verdient, wird er 
die beiden "do{c--;} while(c);" Zeilen komplett wegrationalisieren. 
Sollte er das aus Versehen nicht tun, dann überleg mal, wie viele 
Durchläufe die zweite Schleife wohl macht und wie lange das dauert.

von Norbert (Gast)


Lesenswert?

>>Sollte er das aus Versehen nicht tun, dann überleg mal, wie viele
Durchläufe die zweite Schleife wohl macht und wie lange das dauert.


Hmmm, alle drei Bits beim Prescaler gesetzt wären beim ATmega8 > 2s.
Das wird wohl beim '128er' auch nicht wesentlich anders sein.

Da müsste der Controller schon mit einer Pendeluhr getaktet werden um in 
einen WD-Reset zu laufen ;-)

von Norbert (Gast)


Lesenswert?

Ich würde allerdings folgendermassen initialisieren:

WDTCR = (1<<WDCE);
WDTCR = (1<<WDE)|(1<<WDP2)|(1<<WDP1)|(1 << WDP0);

oder noch einfacher:

http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html

#include <avr/wdt.h>

wdt_enable(WDTO_2S);

von Hc Z. (mizch)


Lesenswert?

Vor dem Enablen des Watchdogs sollte ein wdt_reset() eingefügt werden. 
Der Watchdog-Prescaler läuft nämlich auch dann, wenn kein Enable 
vorliegt und kann sonst irgendwo stehen.

Die NOPs nach dem Enable in Verbindung mit dem nachfolgenden wdt_reset() 
haben dagegen keinen für mich erkennbaren Sinn.  Auch sollten während 
des Watchdog Enable die Interrupts gesperrt werden, wenn dies nicht 
anderweitig gesichert ist.

Übrigens, falls nicht so gewollt:  Die zweite while(c)-Schleife 
durchläuft den vollen Bereich einer Integer und nicht nur 50 
Schleifendurchläufe wie die erste (so sie überhaupt ausgeführt wird - 
ich habe mit Keil nur in uralten 8051-Zeiten gearbeitet, damals konnte 
er die sinnlose Schleife noch nicht erkennen).

von Detlev Neumann (Gast)


Lesenswert?

Danke ich versuche mal eure gedanken für mich umzusetzten

aber bei der zweiten schleife muss c=50 vorstehen habe es aber nur
vergessen abzuschreiben mein fehler

@Norbert leider kann ich die gcc Lib in IAR kompiler nicht verwenden 
(oder ich mache etwas dabei falsch

Danke für die Hilfe

Detlev

von ... (Gast)


Lesenswert?

Detlev Neumann schrieb:
> gcc Lib

Du meinst die avrlibc. Aber wenn ich das in der wdt.h richtig übersetzt 
hab, kommt da aus "wdt_enable(WDTO_2S);" etwa folgendes raus:
1
#define wdt_reset() __asm__ __volatile__ ("wdr")
2
3
  wdt_reset();
4
  WDTCR = (1 << WDCE) | ( 1 << WDE);
5
  WDTCR = (1 << WDE) | (1 << WDP2)| (1 << WDP1) | (1 << WDP0);
Das Original machts halt via inline Assembler und sperrt vorrübergehend 
noch die Interrupts (falls enabled).
Siehe hier:
http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html
http://www.nongnu.org/avr-libc/user-manual/wdt_8h_source.html

von Detlev Neumann (Gast)


Lesenswert?

Danke dem Mann ohne Namen es Funktioniert jetzt

Gruß

Detlev

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.