Atmega328P - WatchDog - SLEEP_MODE - 8 Sekunden

Gast #3157464
Lesenswert?

Hallo,

ich versuche gerade einen Atmega328P in den Schlafmodus 
(SLEEP_MODE_PWR_DOWN) zu bringen. Ein WatchDog soll den uC alle 8sec 
wieder aus dem Modus wecken.

Das WDTCSR Register setze ich auch wie im Datenblatt angeben auf 
B00100001.

Leider schläft dieser lediglich 4 Sekunden anstatt die gewünschten 8 
Sekunden.

Eckdaten: Der uC hat einen 16Mhz Quarz und läuft mit 5V.

Ich weiß leider nicht wie ich das in den Griff bekomme. Evtl. hat jemand 
einen Tipp für mich.

Gruß
Gast #3157557
Lesenswert?

Hier mein Setup für den WatchDog:

// Clear MCUSR, WDRF reset
MCUSR = MCUSR & B11110111;

// Setzen von WDCE und WDE
WDTCSR = WDTCSR | B00011000;

// Setzen des Prescaler. WDP0 und WDP3 auf 1 setzen. (8 sekunden)
WDTCSR = B00100001;

// Enable the watchdog timer interupt.
WDTCSR = WDTCSR | B01000000;
Gast #3157602
Lesenswert?

Liegt es evtl. an der Betriebsspannung?

- The frequency of the Watchdog Oscillator is voltage dependent

Allerdings wenn ich das dazugehörige Diagramm ansehe (Watchdog 
Oscillator Frequency vs. VCC), dann würde ja die Frequenz mit sinkender 
Spannung größer werden.

Ein Zyklus würde ja dann eher noch schneller werden???

Hee???
Gast #3157744
Lesenswert?

Lucky schrieb:
> WDTCSR = B00111001;  //set WDCE to change prescaler
> WDTCSR = B00101001;  //clear WDCE

Das gleiche Verhalten.

Der WatchDog kommt nach 4,x Sekunden wieder aus seinem Tiefschlaf.

Ich habe jetzt auch mal die Versorgungsspannung von 5V auf 3,3V 
geändert.

Nach wie vor erreiche ich nicht die 8 Sekunde.
Gast #3157800
Lesenswert?

Uwe S. schrieb:
> Wird das Programmstück überhaubt übersetzt?
> Bei den Zuweisungen handelt es sich nicht um Konstanten !
> Und wie sieht das Stück Assemblercode aus ?

Ich kann auch schreiben:

WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDE) | (1<<WDP3) | (1<<WDP0);

das sollte eigentlich das gleiche Verhalten haben wie obige 
Schreibweise.

...

Wenn ich zum Beispiel den Wert auf 4 Sekunden setze:

mit

WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDE) | (1<<WDP3);

dann werden 2 Sekunden daraus.
#3157855
Lesenswert?

Hallo,

im Datenblatt zum atmega328p
stehen die genaue Reihenfolge der Anweisungen in C.
S.53f,S.56
1
void WDT_Prescaler_Change(void)
2
{
3
  __asm__ __volatile__ ("cli")
4
  __asm__ __volatile__ ("wdr")
5

6
  /* Start timed sequence */
7
  WDTCSR |= (1<<WDCE) | (1<<WDE);
8

9
  /* Set new prescaler(time-out) value = 1024K (1048576) cycles (~8 s) */
10
  WDTCSR = (1<<WDE) | (1<<WDP3) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0);
11

12
  __asm__ __volatile__ ("sei")
13
}
1
void WDT_off(void)
2
{
3
  __asm__ __volatile__ ("cli")
4
  __asm__ __volatile__ ("wdr")
5

6
  /* Clear WDRF in MCUSR */
7
  MCUSR &= ~(1<<WDRF);
8

9
  /* Write logical one to WDCE and WDE */
10
  /* Keep old prescaler setting to prevent unintentional time-out */
11
  WDTCSR |= (1<<WDCE) | (1<<WDE);
12

13
  /* Turn off WDT */
14
  WDTCSR = 0x00;
15

16
  __asm__ __volatile__ ("sei")
17
}

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