Lass das das TCNT=1 weg. In dem Mode, den du eingestellt hast, erledigt das die Hardware. Wenn du es nochmal zurüchsetzt, geht deine Uhr zu langsam.
Servus,
ich habe mir eine kleine Rundenzeiten-Messanlage gebaut...
Wie kann ich die Messung möglichst genau bekommen?
Ich habe ein Abweichung die ich mir aktuelle nicht erklären kann.
Zunächst kurz wie ich es bisher gelöst habe:
Hardware:
Bild hier
Tiny26 mit externem 11,0592Mhz Quarz
HD44780 Display
Infrarot- bzw. Laserlichtschranke
Software:
Timer1 mit Prescaler 512
Vergleichsregister so eingestellt, dass alle 10ms ein Interrupt ausgelöst wird.
Bei Interrupt wird Zählregister rückgesetzt und die Hunderstel addiert.
Time0 sorgt alle 200ms dafür, dass das angeschlossende LCD aktualisiert wird.
Hier mal der Code des Zählers:
Problem:Code:#include <avr/io.h> #include <avr/interrupt.h> #include "global_time.h" //Variable für Zeitmessung time_struct globalTime; volatile uint8_t milliSeconds = 0; volatile uint8_t secondFlag = 0; ISR(TIMER1_CMPA_vect) { TCNT1 = 0x00; if (100 == ++milliSeconds) { secondFlag = 1; milliSeconds = 0; } } void globalTimeRefresh() { if (secondFlag) { if (60 == ++globalTime.sec) { globalTime.min++; globalTime.sec = 0; } secondFlag = 0; } globalTime.hSec = milliSeconds; } void globalTimeInitialize(void) { /* Timer1: Interrupt genau jede Millisekunde Prescaler 512 Vergleichsregister = F_CPU / 512 / 100 Zähler zurücksetzen, wenn OCR1A erreicht ist */ TCCR1B = (1<<CS13)|(0<<CS12)|(1<<CS11)|(0<<CS10); OCR1A = F_CPU / 512 / 100 + 1; TIMSK |= (1<<OCIE1A); //Interrupt }
Aktuell geht die Zeitmessung 0,3% zu langsam (ca 4s auf 23Min).
Die Genauigkeit des Quarzes ist mit ppm angegeben, also nicht ursächlich für die Abweichung.
0.3% sind bei 11Mhz immerhin 30.000 Takte pro Sekunde - wobei gehen die "verloren"?
Bei der Interruptbehandlung der anderen Interrupts?
Oder durch das manuelle Rücksetzen des Zählers? (TCNT1 = 0);
Es gibt keinerlei atomaren Code, es können also keine Interrupts unterdrückt sein.
Geht vielleicht mein Handy falsch?
MfG
Tobias
Lass das das TCNT=1 weg. In dem Mode, den du eingestellt hast, erledigt das die Hardware. Wenn du es nochmal zurüchsetzt, geht deine Uhr zu langsam.
Disclaimer: none. Sue me.
Leider nicht.
der TIMER1_CMPA_vect-Interrupt wird korrekt ausgelöst, der Timer1 zählt aber bis 0xFF weiter.
Der Tiny26 hat irgendwie keinen Mode um den Zähler nach erreichen von OCR1A automatisch zurückzusetzen. Der Tiny44 hats... mal schauen.
Du betreibst den Timer im "normal" Mode. Schau mal ins Datenblatt und verwende den CTC-Mode. Da fehlt wohl noch ein Bit im TCCRnB. CTCx oder WGMx.
Du schreibst also den Wert nicht nach OCR1A, sondern nach OCR1C und setzt OCR1A=0.Zitat von Manual pp. 73
Ausserdem hast du einen schlechten OCR-Wert. Der Wert muss in 8 Bit passen und die Division muss ausgehen, ansonsten hasst du Ungenauigkeit wegen der Rundungsfehler (Timer geht schneller als gewünscht). Zudem muss da eine -1 hin und keine +1.
Disclaimer: none. Sue me.
Kurz nachdem ich das oben gepostet habe, habe ich das CTC1-Flag auch bemerkt.
Dazu habe ich noch den Interupt auf TOIE1 geändert und es klappt.
Die Genauigkeit muss ich aber noch bestimmen.
/edit
Beim setzen von OCR1C subtrahiere ich noch eine 1:
OCR1C = F_CPU / 512 / 100 - 1;
Und schon zeigt die Uhr die gewünschte Genauigkeit.
Nach 21Minuten ist keine Abweichung in Hundertstel zu bestimmen.
Danke.
Lesezeichen