Forum: Mikrocontroller und Digitale Elektronik Compare Match vorladen Fehlermöglichkeit?


von Chris (Gast)


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?

von Krapao (Gast)


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.

von Chris (Gast)


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...

von Krapao (Gast)


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.

von Krapao (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.