Ich habe das beim Tiny85 so gemacht:
1 | ISR(WDT_vect) // Für WD-Timer
|
2 | {
|
3 | wcount--;
|
4 | WDTCR |= (1<< WDIE); // Watchdog Interrupt muss jedes mal neu aktiviert werden, sonst macht WDT Reset
|
5 | }
|
In der Main wird die WD-Initialisierung einmal aufgerufen und so die
Parameter eingestellt; so werden mit WD_PRESCALE von 0...9 die
Timerzeiten von 16ms bis 8s gewählt - je nach Anwendung.
1 | void Init_WD()
|
2 | {
|
3 | uint8_t wd_timer_prescale;
|
4 | uint8_t wdt_flags;
|
5 |
|
6 | // Watchdog IRQ initialisieren
|
7 | wd_timer_prescale = WD_PRESCALE;
|
8 | if (wd_timer_prescale > 9 ) wd_timer_prescale=9;
|
9 | wdt_flags=wd_timer_prescale & 7;
|
10 | if (wd_timer_prescale > 7) wdt_flags|= (1<<5); // wdt_flags enthält den Prescalerwert (0 .. 9)
|
11 | wdt_flags |= (1<<WDCE);
|
12 |
|
13 | // Watchdoginterrupt aktivieren
|
14 | sei();
|
15 | WDTCR |= (1<<WDCE) | (1<<WDE);
|
16 | WDTCR = wdt_flags | (1<<WDIE);
|
17 | }
|
Man muss nur nur das WDIE-Bit nach jedem Interrupt wieder neu zu setzen.
In der Main kann dann an geeigneter Stelle der Prozessor in den
Power-Down-Schlaf gelegt werden und wird nach Ablauf der WD-Zeit wieder
geweckt.
Mit 'wcount' wird die Anzahl der WD-Interrupts gezählt und bei Null die
gewünschte Aktion gestartet.
Die Fuse WDTON darf nicht aktiviert sein.
So kann man die relativ lange Zeit des WD-Timers für große Zeiten
verwenden und durch den Power-Down-Mode recht stromsparend unterwegs
sein. Mein ATtiny85 braucht dabei ca. 5µA@4V - wenn ich es richtig weiß,
ist das weniger als bei einer Lösung mit einem Timer, weil damit nicht
aus dem Power-Down-Mode geweckt werden kann.