Eine Sekunde wird derzeit folgendermaßen definiert:
Eine Sekunde ist definitionsgemäß das 9.192.631.770-fache der Periode einer Mikrowelle, die mit einem ausgewählten Niveauübergang im Caesiumatom in Resonanz ist. Anders gesagt: das 9.192.631.770-fache der Periodendauer der dem Übergang zwischen den beiden Hyperfeinstrukturniveaus des Grundzustandes von Atomen des Nuklids 133Cs entsprechenden Strahlung. http://de.wikipedia.org/wiki/Sekunde
Von all dem weiß der AVR aber nichts. Gemäß seinem internen Takt von 1MHz besteht eine Sekunde aus einer Millionen Takte. Da der interne Takt aber recht ungenau ist, ist auch eine Sekunde für den AVR nicht so genau definiert. Möchte man den AVR aber z.B. als Uhr benutzen, ist das sehr unpraktisch. Abhilfe muss also her.
Deswegen wollte ich - schon bevor ich die falschen Fuse-Bits gesetzt habe - einen externen Quarz-Kristall mit dem AVR verbinden, um ein stabiles Taktsignal zu haben. Da ich in dem Datenblatt etwas über einen externen 32.768kHz Kristall gelesen hatte, für den der AVR ausgelegt sei, hatte ich diesen zuerst versehentlich für einen Ersatz zum internen Taktgeber gehalten. Daher auch der Artikel "Fuse-Bits sind böse...".
Nachdem ich diesen Fehler wieder hingebogen habe, habe ich den externen Kristall mit den korrekten Eingängen TOSC1 und TOSC2 verbunden. Nachdem ich dann noch den zweiten Timer so eingestellt habe, dass er den externen Resonator auch verwendet, hatte ich plötzlich ein recht stabiles Signal von 32.768kHz zur Verfügung.
Auch wenn diese Zahl auf den ersten Blick recht unhandlich aussieht, fällt auf, dass sie sich prima durch z.B. 1024 teilen lässt - eine Zahl, die der AVR auch mag ;) Also benutze ich einen Vorteiler von 1024 und löse alle 32768/1024 = 32 Takte einen Interrupt aus - also genau 1 Mal pro Sekunde.
Dieser Takt ist bedeutend genauer als der Takt des AVR. Mit diesem hatte ich innerhalb von 24 Stunden einen Fehler von mehr als 5 Minuten. Mit dem Uhrenquarz hatte ich in 12 Stunden einen Fehler kleiner als eine Sekunde. Wenn das mal kein Unterschied ist :)
Hier noch einige ausgewählte Code-Schnipsel, die das eben gesagte verdeutlichen sollen:
void main(){ //... ASSR |= 1< TCCR2 = (1<<< TIMSK |= 1< //... } SIGNAL (SIG_OVERFLOW2){ TCNT0 = -32; // 1s: Prescaler 1024, resonator freq. 32.768kHz // ... }
Der Rest des Codes sollte eigentlich recht unverändert geblieben sein. Ich stelle ihn trotzdem mal zum Download, damit ihr einen Gesamteindruck kriegt ;)
Mein nächster Plan ist jetzt, den AVR noch mit einem Funkmodul auszustatten, über das er sich die aktuelle Atomzeit besorgen kann, um auch den kleinen Gangunterschied des Quarzes zu korrigieren...