Ein interessantes Feature möchte ich hier speziell erklären, und zwar die Programmierung des Power Down Modes.
Wird der Mikrocontroller in diesen Modus geschaltet, verbraucht er nur noch ca. 1µA. Das ist so wenig, dass die Batterien quasi ewig halten bzw. die Batterien durch Überalterung bereits aufgeben würden, bevor ihre Kapazität verbraucht wurde. Im Power Down Mode halten alle Taktgeneratoren an. Die Register, der Speicher (RAM) und die Programmstelle, an der fortgefahren werden muss überstehen aber den Power Down Mode. D.h. das Programm fährt nach dem Aufwecken genau an der Stelle fort und die Unterbrechung ist somit vom Programmablauf her vollkommen irrelevant!
Übrigens gibt es noch weitere Stromsparmodi bei den Mikrocontrollern, so dass man auf ähnliche Weise beispielsweise ein Gerät zur Datenerfassung (z.B. Temperatur) bauen könnte, welches sich alle paar Minuten kurz aufweckt, Werte mißt und dann wieder schlafen geht. Hierzu müsste man allerdings einen Modus wählen, in dem ein Wecken per Timer möglich ist.
Um den Mikrocontroller schlafen zu legen, muss zunächst der Power Down Mode einmalig bei Programmstart konfiguriert werden. Mit den drei Bit im MCUCR Register wird der Sleep Modus (s. obige Tabelle) gewählt.
// INT0 Enabled, Mode: Low Level MCUCR |= 0x00; GICR = 0x40; // configure power down mode cbi(MCUCR,4); sbi(MCUCR,5); cbi(MCUCR,6); // disable interrupt as default cli(); |
Wenn der Mikrocontroller schlafen gelegt werden soll, werden die Interrupts eingeschaltet. Alle Ausgänge müssen zurückgesetzt werden, damit kein Strom verbraucht wird (im Fall des Kurzzeitweckers würde die LED Anzeige eingeschaltet bleiben und Strom verbrauchen). Dann kann der "sleep" Befehl scharf geschaltet und schließlich aufgerufen werden:
clear_display(); sei(); // enable interrupts to make wakeup possible sbi(MCUCR, SE); // Sleep enable bit makes "sleep" asm instruction available asm volatile("sleep"); // go to sleep |
Der µC ist jetzt im Power Down Mode. Per Taster kann er geweckt werden. Wenn dies passiert ist, wird zunächst der Interrupt-Handler aufgerufen. Da hier aber nichts zu tun ist bei dem Kurzzeitwecker, ist die Methode leer:
SIGNAL(SIG_INTERRUPT0) { // nothing to do here, interrupt is only used to wake up } |
Danach läuft das Programm direkt nach dem sleep Befehl weiter. Hier sollte jetzt der "sleep" Befehl wieder deaktiviert werden (dies wird so von Atmel empfohlen). Außerdem können Interrupts wieder ausgeschaltet werden.
cbi(MCUCR, SE); // disable sleep instruction cli(); // disable interrupts |