Hallo,
ich habe folgendes Problem mit meinem Code auf einem Atmega8, Timer1
16-bit.
Ich messe die Zeit zwischen zwei Ereignisse und nehme die Differenz
(Zeitdifferenz, größer 16-bit). Nach Ablauf dieser Zeit möchte ich ein
Compare Match auslösen.
Hierzu schreibe ich die gemessene Zeit in eine 32-bit Variable und
addiere den aktuellen Timer-Stand (TCNT1) hinzu.
Nun zähle ich diese Zeit im OVF-Vektor herunter bzw. inkrementiere immer
um 65536 bis diese Zeit kleienr 16-bit ist. Dann schreibe ich diesen
Wert in das OCR1A-Register und schalte das Compare Match Interrupt frei.
Soweit so gut, hier der "gedankliche" Code dazu:
1 | ISR (TIMER1_OVF_vect){
|
2 |
|
3 | // Countdown
|
4 | if ( Zeitdifferenz > 65535 ){ // Ist die Zeit, die heruntergezählt werden muss noch größer als 16-bit
|
5 | Zeitdifferenz -=65536; // wenn ja, die Zeit um 65536 dekrementieren, da ein Overflow aufgetreten ist
|
6 | if ( Zeitdifferenz <= 65535){ // erneute Prüfung! nach dekrementieren
|
7 | OCR1A = Zeitdifferenz; // nun kleiner 16-bit, mit dieser Zeit vorladen
|
8 | if ((TIFR & (1 << OCF1A))){ // Ist das Compare Match Flag schon gesetzt und würde direkt ausgeführt werden?
|
9 | TIFR = (1 << OCF1A); // Flag löschen, da falsch, durch schreiben einer 1
|
10 | }
|
11 | TIMSK |= (1 << OCIE1A); // Compare Match Interrupt aktivieren
|
12 | }
|
13 | }
|
14 | }
|
Nun habe ich mir überlegt, sollte Zeitdifferenz z.B. vor dem Anspringen
des OVF-Vekotr nur minimal größer sein als 16-bit, z.B. 65540, so wird
das hier noch dekrementiert in der ersten if-Abfrage und OCR1A mit 5
vorgeladen. Nur wird der Timer während der Abarbeitung (dieser paar
Anweisungen) bereits weiter als 5 gezählt sein und dadurch geht mir
dieser Compare Match verloren bzw. wird erst 65536 Timerzyklen später
ausgelöst. Liegt hier ein Denkfehler von mir vor? Ich glaube nicht oder?
Und wenn es so wäre, wie löst man das am geschicktesten, um das Problem
zu umschiffen?