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ß
> Das WDTCSR Register setze ich auch wie im Datenblatt angeben auf > B00100001. Wie setzt Du das ∗genau∗?
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;
mamamia schrieb: > Leider schläft dieser lediglich 4 Sekunden anstatt die gewünschten 8 > Sekunden. Aus dem Kopf wette ich, dass es 4,3 Sekunden sind…Datenblatt lesen!!!
Hmm??? Ich lese das Datenblatt nun zum x-ten Mal. Ich finde die Lösung nicht. Vielleicht kannst du mir auf die Sprünge helfen?
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???
mamamia schrieb: > MCUSR = MCUSR & B11110111; Was soll das denn bewirken? Wo ist B11110111 definiert? int B11110111 = 0; ??? mfg.
WDTCSR = B00111001; //set WDCE to change prescaler WDTCSR = B00101001; //clear WDCE Versuch das mal.
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.
mamamia schrieb: > Der WatchDog kommt nach 4,x Sekunden wieder aus seinem Tiefschlaf. Kann der Watchdog auch schlafen?
Michi schrieb: > mamamia schrieb: >> Der WatchDog kommt nach 4,x Sekunden wieder aus seinem Tiefschlaf. > Kann der Watchdog auch schlafen? Vielleicht hätte ich schreiben sollen, das der Hund alle 4s bellt - anstatt alle 8s.
Wird das Programmstück überhaubt übersetzt? Bei den Zuweisungen handelt es sich nicht um Konstanten ! Und wie sieht das Stück Assemblercode aus ?
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.
Hallo, besser von der Schreibweise, überprüfe ich jetzt nicht. Du gehst auf meine Fragen nicht ein ! Noch mal deutlicher: B00111001 ist keine Konstante in "C" !
Uwe S. schrieb: > Noch mal deutlicher: B00111001 ist keine Konstante in "C" ! Ja, da stimme ich dir zu. B00111001 soll einfach ein Binärwert darstellen. Ich hätte vermutlich auch einen Hexadezimal Wert (0x39) angeben können und diesen dem Register zuweisen können.
Hallo, ich würde die in avr gcc vorhandenen Macros verwenden. http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html http://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog Dann müsste man sich auch mit dem Timing der Befehlsabfolge auseinander setzen.
1 | #include <avr/wdt.h> |
2 | wdt_enable(WDTO_8S); |
3 | wdt_reset(); |
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 | }
|
Hallo, sei so nett und beschreibe, wie das Problem gelöst wurde, so könnten auch anderer Leser davon profitieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.