Hallo,
ich bin gerade dabei mir ein 32 Bit Zeitstempel zu programmieren. Das
funktioniert auch fast perfekt. Um den Code zu testen, habe ich mir eine
Warteschleife programmiert, die eine LED alle X Mikrosekunden
ausschaltet und dann sofort wieder einschaltet. Das funktioniert auch
nur soweit, nur zwischen drin, kommt es immer wieder zu einem
Doppelpuls(Siehe Oszibild). Woher kommt der Ausreißer?
Timer Klasse: CPP-Datei
static Systemtimer* pSystemtimer;
Pate schrieb:> cli();>> time=(uint32_t)(TCNT1)+pSystemtimer->Time;
Was wenn "zwischen" diesen beiden Zeilen der Timer überläuft, TCNT1 also
0 zurückliefert, aber der Timerinterrupt noch nicht ausgeführt wurde,
also pSystemtimer->Time noch nicht um 0x10000 erhöht wurde? Dann erfährt
deine Zeit einen Sprung rückwärts...
ATOMIC_BLOCK mach in einer ISR wenig sinn.
> time=(uint32_t)(TCNT1)+pSystemtimer->Time;
wenn TCNT1 überläuft während die Berechnung läuft könnte das zu
Problemen kommen. Da hilft auch das cli und sei nicht weil er Trotzdem
weiterzählt.
Pate schrieb:> Achso, dann muss ich das Überlaufbit mit betrachten.
Das bringt leider auch nix, was wenn der Überlauf kommt zwischen der
Abfrage des Bits und Abfrage von TCNT1 - egal in welcher Reihenfolge
dies stattfindet?
Eigentlich müsstest du den Timer temporär anhalten...
Wie wäre es mit einem zweiten Timer-Register, bei dem du per
Flag-Register die Aktualisierung stoppst, wenn du Auslesen möchtest?
Oder lass deinen Code zum Auslesen mit dem IRQ synchronisieren. Da gibt
es viele Möglichkeiten, Timer anhalten würde ich nie machen, wenn's denn
genau sein soll.
PS: Mit ARM wäre das nicht passiert (SCNRT) ;)
Man könnte nach dem Einlesen des tcnt1 während disabled interrupts und
wenn der tcnt <max/2 ist, das tifr überprüfen, ob ein Überlauf
stattgefunden hat und noch nicht abgearbeitet wurde. In diesem Falle
muss der zu speichernde timerwert entsprechend erhöht werden.
Das ein Timer soo viel ärger machen kann...
Das mit der Synchronisierung versuche ich derzeit. Ich habe mir in der
Klasse eine Funktion gebaut, die Reibungslos funktioniert. Nur wenn ich
mir eine Warte FUnktion in der Main baue, gehts daneben...
greg schrieb:> PS: Mit ARM wäre das nicht passiert (SCNRT) ;)
Wie, ARM baut auch Timer? Du meinst 'systick'?
Die Überlaufe eines Timers sind doch kein Problem, man muß sie nur
beachten!
In der Routine "ISR(TIM1_CAPT_vect)" kann man sehen, wie es geht:
http://www.mino-elektronik.de/fmeter/fm_software.htm#bsp11Georg G. schrieb:> Wie wäre es mit "zweimal ablesen". Dann kannst du per Plausibilität> entscheiden, ob und bei welcher Ablesung dein Timer übergelaufen ist.
Auch das kann man machen, wenn es nicht zeitkritisch ist.
Und wenn du den Timer stoppst und anschließend zu TCNT1 x addierst,
wobei x die Anzahl der Takte ist, die es von Stoppen bis nach der
Berechnung braucht (x könnte man aus dem Assemblerlisting berechnen)?