@ Lukas -- (lukas)
>Das Problem ist blos, ich möchte mehrere Stunden lang Messwerte in einem
>Intervall von 50ms ausgeben. Das beste Ergebnis bekommt man bei einem
>Prescaler von 8 und einem CTC-Wert von 205. Dann erhalte ich intervalle
>von 50,048828ms das bedeutet nach einer Stunde einen Zeitverzug von
>+3,51 Sekunden.
>Meine Lösung: Ich arbeite weiterhin mit einem 32768kHz Quarz am Timer
Das sind eher 32768 Hz ;-)
>und einem ATmega16 mit 16Mhz. Ich nehme einen Prescaler von 8 und einen
>CTW-Wert von 204 statt 205. Dann erhalte ich ein Intervall von
>49,804688ms. Wenn ich dann nach jedem Interrupt vom Timer den Timer für
>3125 Takte anhalte, müsste der Zeitverzug gleich null sein.
>Ich werde bei meiner nächsten Reicheltbestellung ein paar Uhrenquarze
>ordern und testen, ob meine Berechnung so hinkommt.
Nicht testen, DENKEN!
>Falls jemand einen Fehler findet oder einen Besseren Vorschlag hat,
>immer her damit!
50ms kann man mit fast jeder beliebigen Quarzfrequenz genau erzeugen.
Mit 32,768 kHz wirds eng, ja, aber man kann tricksen.
Der einfache Ansatz ist einfach ein normaler Quarz mit 1, 4, 8, whatever
MHz am Hauptoszillator und gut. Damit kann man die 50ms genau erzeugen,
einziger Fehler ist die Toleranz des Quarzes von ca. +/- 100ppm ohne
Abgleich.
Wenn man Stom sparen will, muss man auf den Uhrenquarz und [[Sleep
Mode]] gehen. Aber 32768 / 20 Hz (50ms) = 1638,4. Dumm, das ist keine
Ganzzahl. Aber es gibt ja Festkommaarithmetik!!
Siehe auch AVR - Die genaue Sekunde / RTC.
Ach ja, dein CTC Wert ist falsch. Denn die Periode ist nicht 205 Takte
sondern 206, von 0..205! Damit ist deine Periodendauer 50,293 ms ;-)
Mit einem Vorteiler von 204 erhält man eine Periodendauer von 205*8
Takten, macht die oben genannten 50,0488ms. Der ideale Teilerfaktor ist
204,8, ein Fehler von 0,2 Takten bzw. 0,9765625 Promille, macht halt
deine 3,51s/ Stunde.
Aber 0,2 Takte Fehler klingt einfach. Denn man kann einfach 4 Perioden
durch 205 teilen und die 5. Periode durch 204, macht im Mittel 204,8 ;-)
Also muss man nur im Timer Interrupt eine (statische) Variable
hochzählen (0..4) und bei vier den Compare Wert für den CTC-Modus auf
203 setzen, sonst auf 204. Schwups hat man ideal einen 50ms Takt, der
lediglich um max. acht 32KHz Takte (244µs) um den idealen Zeitpunkt
jittert.
1 | ISR () {
|
2 | static uint8_t jitter;
|
3 |
|
4 | if (jitter==4) {
|
5 | jitter=0;
|
6 | OCR2A = 203;
|
7 | } else
|
8 | jitter++;
|
9 | OCR2A = 204;
|
10 | }
|
So in etwa.
MfG
Falk