Watchdog im Interrupt-Mode

OP #5015371
Hallo alle zusammen,

ich möchte den Watchdog des AVRs (hier ein Mega328p) im Interrupt-Mode 
(nicht System-Reset)benutzen. Das habe ich auch schon gemacht und 
funktionierte immer prima, allerdings war der Time-out immer nur auf den 
16 ms eingestellt. Jetzt will ich allerdings eine andere Zeit 
einstellen, das klappt aber nicht. Ich bin einfach zu doof dazu ne 
andere Zeit einzustellen, kann mir mal jemand bitte das Brett vom Kopp 
nehmen? Hier mein Bleistift:
1
#include "lcd.h"
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
void setUpAvr(void){
6
    /* insert your hardware initialization here */
7
    lcd_init(LCD_DISP_ON);
8
    lcd_clrscr();
9
    lcd_puts("WDT Test");
10
    
11
    WDTCSR |= (1 << WDCE)|(1 << WDIE)|(1 << WDP2)|(1 << WDP1);
12
    // enable interrupts
13
    sei();
14
}
15
int main(void)
16
{
17
    setUpAvr();
18
    
19
    for(;;){
20
        /* insert your main loop code here */
21
        asm("wdr");
22
        _delay_ms(25);
23
    }
24
    return 0;   /* never reached */
25
}
26
ISR(WDT_vect){
27
    lcd_clrscr();
28
    lcd_puts("Watchdog");
29
    _delay_ms(1000);
30
}
#5015383
Setzen von WDCE und Änderung am Prescaler darf nicht zeitgleich 
erfolgen.
Erst WDCE setzen, dann den Rest.

Atmel:
1
void WDT_Prescaler_Change(void) { 
2
  __disable_interrupt(); 
3
  __watchdog_reset();
4
  /* Start timed  equence */ 
5
  WDTCSR |= (1<<WDCE) | (1<<WDE); 
6
  /* Set new prescaler(time-out) value = 64K cycles (~0.5 s) */ 
7
  WDTCSR  = (1<<WDE) | (1<<WDP2) | (1<<WDP0); 
8
  __enable_interrupt();
9
}
OP #5015598
Georg G. schrieb:
> In der Service Routine solltest du keine langwierigen Ausgaben machen
> und auch das Delay ist kontraproduktiv. Setze ein Flag und verlege das
> alles in die Hauptschleife.

Das ist ja nur ein Beispiel-Code der das Problem zeigt ;)

Peter D. schrieb:
> M. K. schrieb:
>> Jetzt will ich allerdings eine andere Zeit
>> einstellen
>
>
1
> #include <avr/wdt.h>
2
> 
3
>   wdt_enable( WDTO_2S );
4
>

Ich will keinen System-Reset, macht die Verwendung von der wdt.h aber 
immer soweit ich weiß. However, ich habs probiert. Die ISR wird hierbei 
anscheinend nicht angesprungen. Das Display blitzt kurz auf (mit Oszi 
hab ich noch nicht geschaut, tippe aber auf 16 ms ;)) und bleibt dann 
Dunkel.

Carl D. schrieb:
> Setzen von WDCE und Änderung am Prescaler darf nicht zeitgleich
> erfolgen.
> Erst WDCE setzen, dann den Rest.

Das ändert leider nichts an dem Problem.
Gast #5015615
Hallo M. Köhler,

M. K. schrieb:
> Das ändert leider nichts an dem Problem.

Ich mache es immer so, wie es im zugehörigen Datenblatt beschrieben 
wurde.
Damit hatte ich nie Probleme.
Man muss evtl. noch das globale Interrupt Flag abschalten, um im 
Zeitrahmen zu bleiben.
Ich schreibe deshalb diese Abschnitt in Assembler.
Gast #5015637
Karl M. hat Recht.
Konkret sieht es bei mir in Assembler so aus:
1
  cli
2
  wdr
3
  lds    tmp0,WDTCSR
4
  ori    tmp0,(1<<WDCE)+(1<<WDE)
5
  sts    WDTCSR,tmp0
6
  ldi    tmp0,(1<<WDIE)+(1<<WDP2)+(1<<WDP1)+(1<<WDP0)  ; 2 s
7
  sts    WDTCSR,tmp0
8
  sei
Gast #5015648
Ohne 'Vorleben' geht es auch etwas kürzer:
1
  ldi    tmp0,(1<<WDCE)+(1<<WDE)
2
  sts    WDTCSR,tmp0
3
  ldi    tmp0,(1<<WDIE)+(1<<WDP2)+(1<<WDP1)+(1<<WDP0)  ; 2 s
4
  sts    WDTCSR,tmp0
5
  sei
OP #5015667
Ich hab das Brett gefunden. Ich schrieb:
1
...
2
WDTCSR |= (1 << WDCE)|(1 << WDE);
3
WDTCSR |= (1 << WDP2)|(1 << WDP1);
4
...

Und richtig wars/ists:
1
...
2
WDTCSR = (1 << WDCE)|(1 << WDE);
3
WDTCSR = (1 << WDP2)|(1 << WDP1);
4
...

Was für ein blödes Brett...
Gast #5015692
M. K. schrieb:
> Und richtig wars/ists:
> ...
> WDTCSR = (1 << WDCE)|(1 << WDE);
> WDTCSR = (1 << WDP2)|(1 << WDP1);

Nicht wirklich !

Was ist mit dem Bit WDIE und der zugehörigen Interruptfreigabe?

Ich schreibe mir dazu gerne alle Register und deren Bit-Namen aus dem 
Datenblatt in den Quellcode:

MCU Status Register
MCUSR
– – – – WDRF BORF EXTRF PORF
MCUSR &= ~(1<<<WDRF)

Watchdog Timer Control Register
WDTCSR
WDIF WDIE WDP3 WDCE WDE WDP2 WDP1 WDP0
const uint8_t WDR_TIMER_MODE = (0<<WDP3) | (1<<WDP2) | (1<<WDP1) 
(1<<WDP0); // time out aprox. 2 sec
WDTCSR |= (1<<WDIF) | (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDIE) | WDR_TIMER_MODE;
OP #5015881
Karl M. schrieb:
> Was ist mit dem Bit WDIE und der zugehörigen Interruptfreigabe?

Da hast du natürlich recht, das muss noch entsprechen gesetzt werden. 
Kernproblem war halt, dass ich die Zeit nicht umgestellt bekam und das 
oben Beschriebene war das Problem. Ich hätte da nicht verodern dürfen 
wie es auch im Datenblatt steht, das war mein Brett vorm Kopf ;)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.