Compare Match vorladen Fehlermöglichkeit?

Gast #2639659
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
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
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
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
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

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.