Hallöchen,
ich habe mir gerade mittels des Timer-Tutorials eine einfache Uhr
geschrieben, aber irgendwie hat sie einen kleinen Versatz von ein paar
ms pro 10s. Könntet ihr event. mal kurz drüberschauen, und berichten, wo
das Problem sein könnte?
20 MHz;Timer0
1
voidTIMER_INIT(void)
2
{
3
// Konfiguration von 8-bit Timer/Counter0
4
TCCR0B=(1<<CS01);// Vorteiler:8
5
TIMSK0|=(1<<TOIE0);// Aktivierung des Timer/Counter0-Overflow-Interrupts
6
7
sei();// Aktivierung der Interrupts auf globaler Ebene
Marcel schrieb:> ISR(TIMER0_OVF_vect)> {> // 20000000/8/250(Frequenz;Vorteiler;Zählerschritte) = 10000 Takte pro> Sekunde>> TCNT0 = 12; // Vorladen, um 250 Zählerschritte für einen genaueren> Ausgangswert zu erreichen
Das taugt grundsätzlich nichts. Bis der Timer da angekommen ist, hat er
schon wieder ein paar Schritte weitergezählt. Der bleibt in der ISR ja
nicht bei 0 stehen.
>20 MHz;Timer0
Daraus schliesse ich mal, dass du einen moderneren Atmega hast, als den
Atmega8 mit seinem 8048-Timer-Revival-Mode.
Der kann auch CTC mit Timer0. Damit kriegst du das exakt hin.
mfg.
> aber irgendwie hat sie einen kleinen Versatz von ein paar ms pro 10s
Ist Deine Taktquelle genauer als 10e-4?
Und: Steig auf einen CTC-Modus um, Overflow mit TCNT vorladen ohne
spezielle Vorkehrungen ungenau.
Mein Problem ist jetzt nur, dass das Beispielprogramm mit 1 MHz F_CPU
rechnet und so mit dem Vorteiler auf eine gerade Zahl im 8bit-Bereich
kommt.
Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125. Wie
kann ich denn mit dieser Zahl OCR0A steuern?
Liebe Grüße,
Marcel
Hi
>Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125.
Es sind es 77,125.
>Wie kann ich denn mit dieser Zahl OCR0A steuern?
Nach 7 Interrupts den OCR-Wert auf 78 erhöhen und beim nächsten
Interrupt wieder auf 77 setzen.
Oder einen 18,432MHz Quarz nehmen.
MfG Spess
Marcel schrieb:> Bei 20 MHz und einem Vorteiler von z.B. 256 bekomme ich aber 78,125. Wie> kann ich denn mit dieser Zahl OCR0A steuern?
20.000.000 / 64 = 312500
OCR0A = 249
312500 / (OCR0A + 1) = 1250
ISR(TIMER0_COMPA_vect)
{
static int nTimerCT = 0;
nTimerCt++;
if(nTimerCt == 1250)
{ //1s
nTimerCt = 0;
mfg.
Guten Abend allerseits,
vielen lieben Dank an euch beide.
Ich habe Spess' Weg gewählt, da ich sonst wohl noch einen Zähler für die
Anpassung auf Millisekunden bräuchte.
Es scheint einwandfrei zu funktionieren... ;
Einen wundervollen Abend,
Marcel
Hi
>es scheint ja soweit zu gehen, aber ich würde gern noch verstehen>warum.;-)>Ich komm irgendwie nicht dahinter...
8 x 77,125 = 617
Geht aber nicht da es nur ganzzahlige Takte gibt. Deshalb
7 x 77 + 78 = 617
MfG Spess
Hey,
das bedeutet dann aber auch, dass ich eine auf die ms zugreifende
Applikation nur alle 8 ms (bzw. Zyklen) um die 125 Takte synchronisieren
kann?
LG, Marcel
Hi
>das bedeutet dann aber auch, dass ich eine auf die ms zugreifende>Applikation nur alle 8 ms (bzw. Zyklen) um die 125 Takte synchronisieren>kann?
Welche '125 Takte'?
Du hast 7 mal eine 'Millisekunde' die 0,162% zu kurz sind und eine
'Millisekunde' die 1,134% zu lang ist. Damit mußt du leben oder einen
geeigneten Quarz einsetzen.
MfG Spess
Deine Uhr geht die meiste Zeit minimal vor und korrigiert sich mit dem 8
Takt.
Wenn Dir das nicht passt hilft nur ein passender Quarz. Die sind meist
problemlos zu haben, bewirken aber meist, dass der Rechner etwas
langsamer läuft. Also 18,?? statt 20MHz oder 14,?? statt 16 MHz.
Eine weitere Möglichkeit ist, Du schaust Dir mal den Artikel: "Die
genaue Sekunde" an