Compare Match vorladen Fehlermöglichkeit?

Gast #2639659
Lesenswert?

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?
Gast #2639773
Lesenswert?

Du kannst TCNT1 vorladen, um mit weniger Takten zum Overflow zu kommen. 
Dann entsprechend mehr Takte im CTC abpassen.

Oder du kannst nur mit CTC arbeiten und die Wartezeit in mehrere, 
ähnlich lange Zeiten stückeln.
Gast #2639779
Lesenswert?

Den Timer wollte ich durchlaufen lassen, da er ständig die Zeitmessung 
nimmt und immer Endzeit-Startzeit zur Differenzbestimmung misst. Daher 
wollte ich ungern den Timer irgendwo vorladen oder nullen bei Compare 
Match...
Gast #2639794
Lesenswert?

Dann würde ich nur mit OCIE1A arbeiten und Zeitdifferenz in handliche 
(in etwa gleich große) Portionen für OCIE1A zerlegen (Bsp. 80000 Takte = 
2x40000 Takte). Innerhalb der ISR für Compare Match dann einen Zähler 
für die Portionen runterzählen und wenn die letze Portion dran war 
Aktion auslösen.
Gast #2639803
Lesenswert?

Die Portionen müssen nicht gleich groß sein. Es kann vorkommen, dass die 
letzte Portion 1 Takt länger sein muss. Die Zerlegung in Portionen würde 
ich nicht in der ISR selbst machen, sondern im Anwendungsteil.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren