Hallo Forum,
ich nutze 3 Channel von Timer1 eines STM32F105 um Frequenzen bis 1kHz zu
messen. Ich verwende die direkte Methode mit Capture Compare Interrupts,
da ich jede Flanke zählen muss und auch den Dutycycle benötige.
Mein Problem ist, dass ich immer wieder Sprünge in der Frequenz um +
oder - einen Überlauf habe. Timer 1 hat einen eigenen Update Interrupt
und die Capture Compare Channel münden in einem Sammelinterrupt. Das
bereitet mir Probleme bei der Ermittlung der passenden Überläufe bzw.
der Synchronisation zwischen dem gespeicherten Capture Wert und der
zugehörigen Anzahl Overflows. Der Timerwert wird bei einer Flanke in
einem Register zwischen gespeichert, aber wie bekomme ich den
zugehörigen Überlaufwert? Die Reihenfolge, wie die Interrupt Flags
gesetzt werden, muss ja nicht zur Aufrufreihenfolge der Interrupt
Funtkionen passen.
Aktuell hat der Update Interrupt eine höhere Priorität als der ander
Interrupt. Außerdem zähle ich die Überläufe (jeweils 1 Counter pro
Channel) im Update Interrupt nur hoch, wenn das entsprechende CC
Interrupt Flag nicht gesetzt ist. Der CC Interrupt ist auch etwas
länglich, da ich aktuell sofort die Frequenz berechne und im worst case
alle 3 Kanäle hintereinander in einem Interrupt abgearbeitet werden
könnten. Das ist nicht schön, passt m.M. aber nicht zu dem +-1 Überlauf
Problem.
Wie löst man das sauber? Insbesondere auch mit 3 Kanälen
Kann man mit der viel zitierten reziproken Frequenzmessung auch den DC
bestimmen? Kann ich mit 4 Channeln des Timers 3 Signale auswerten, also
mit einer gemeinsamen Torzeit arbeiten? So ganz klar ist mir das noch
nicht.
Gruß
Bernd
Der Knackpunkt ist doch, wie stelle ich fest, welches Interrupt Flag
zuerst gesetzt wurde, wenn beide sehr kurz nacheinander gesetzt wurden
und es nicht eindeutig ist, in welcher Reihenfolge die Interrupt
Funktionen ausgeführt werden...
Der Timer läuft mit 72MHz durch. Aber selbst wenn er langsamer läuft,
kann nie ausgeschlossen werden, dass Flanke und Überlauf zeitlich so nah
beieinander liegen, das beide Flags gesetzt sind, aber die Reihenfolge
unklar ist.
Bernd schrieb:> Mein Problem ist, dass ich immer wieder Sprünge in der Frequenz um +> oder - einen Überlauf habe.
Arbeite nicht mit absoluten Zählerwerten, sondern mit der Differenz
zum letzten ausgelesenen Zählerwert. Dann "rechnet" sich der Überlauf
von allein heraus.
So wie das z.B. beim Arduino und seinen millis() gemacht wird:
https://forum.arduino.cc/index.php?topic=285280.msg2000555#msg2000555
Lothar M. schrieb:> Arbeite nicht mit absoluten Zählerwerten, sondern mit der Differenz> zum letzten ausgelesenen Zählerwert. Dann "rechnet" sich der Überlauf> von allein heraus.
Hallo Lothar,
danke für deine Antwort.
ich verstehe nicht, wie in einer Differenz von zwei Zählerwerten mehrere
Überläufe enthalten sein sollen?
Die Interrupts von Capture und Überlauf müssen die gleiche Priorität
haben. Sonst wird das nichts!
Ein Beispiel mit TIM9 findest Du hier:
Beitrag "reziproker Frequenzzähler mit STM32F4Discovery"
Sieh Dir "void TIM1_BRK_TIM9_IRQHandler(void)" an.
Genau das mit den zwei Interrupts macht mir noch Probleme.
Ich versuche das gerade gegen einander zu verriegeln, aber noch ohne
Erfolg.
Der Reziprokzähler scheint ja von dir (m.n.) zu sein.
Kann ich damit mehrere Kanäle eines Timers gleichzeitig als
Frequenzeingang nutzen? Und kann ich irgendwie zusätzlich den duty cylce
bestimmen?
Habe an dem Beispiel aber jetzt verstanden, wie ermittelt wird, welches
Flag zuerst war.
1
if((TIM9->SR&TIM_SR_UIF)&&(zeit_low<0x8000))// evtl. Ueberlauf T9 noch offen?
Mit dem <0x8000 ergibt sich, dass zuerst der Überlauf und dann die
Flanke aufgetreten sein muss. Clever.
Nur wo wird "ueberlauf" zurück gesetzt und warum werden 2 Port Pins
konfiguriert, aber nur ein Capture Channel verwendet?
Bernd schrieb:> Nur wo wird "ueberlauf" zurück gesetzt und warum werden 2 Port Pins> konfiguriert, aber nur ein Capture Channel verwendet?
Ein Capture-Eingang wird mit Vorteiler / 8 der andere direkt verwendet,
auch wenn er im Beispiel ausmaskiert ist.
Mit Pulsweite habe ich auch etwas gemacht:
http://mino-elektronik.de/FM_407/fmeter_407.htm#a5
Weiter oben zu dem Beipiel findest Du noch einen 4-kanaligen Zähler, und
ganz unten mein 10-stelliges 'Spitzenmodell' ;-)
Du benutzt anscheinend zwei Timer Kanäle für einen Pin Eingang, um
Frequenz und DutyCycle zu bestimmen. Kann man nicht einen Timer Kanal
nutzen und immer die zu triggernde Flanke umkonfigurieren? Dann könnte
man doch mit einem Timer 3 Frequenzeingänge realisieren.
Bernd schrieb:> Kann man nicht einen Timer Kanal> nutzen und immer die zu triggernde Flanke umkonfigurieren?
Bei 500 kHz bestimmt nicht mehr. Für 1 kHz probiere es aus, wie es bei
kleinen Pulsweiten funktioniert.
Also ich habe die Version von hier
http://mino-elektronik.de/progs/STM32F4xx/pwm_f407/f_mess.c mit
Umkonfigurieren der Flanke anstelle zweier interner Kanäle mit fester
Flankenzuordnung ausprobiert. Das scheint aber nur im Bereich 20% bis
80% Dutycycle zu funktionieren. Ansonsten gibt es sporadische
Frequenzsprünge nach unten. Das hätte ich noch nicht so früh erwartet.
In den Randbereichen <5% und >95% wird es dann erwartungsgemäß deutlich
schlimmer.
Es gibt ja 4 Fälle zu betrachten, wenn das CaptureCompare und das
TimerUpdate Flag quasi gleichzeitig gesetzt werden. 2 Davon sind
problematisch und bedürfen ggf. einer gesonderten Betrachtung.
Ein Fall wird "offensichtlich" im Post vorher verlinkten Code behandelt
(Im CC Interrupt und Zähler <0x8000).
Müsste man nicht eigentlich auch im Update Interrupt überprüfen, ob das
CC Flag gesetzt ist?
Im Fall, dass beide Flags (Update und CC) "gleichzeitig" auftreten und
zuerst die Update Interrupt Funktion ausgeführt wird und gleichzeitig
der gespeicherte Zählerwert >0x8000 ist bedeutet doch, dass CC Interrupt
zuerst da war, nun aber die Update Interrupt Funktion vorher ausgeführt
wird. Dann ist der Überlaufzähler nach dem ++ für den zugehörigen
Zählerwert einen zu groß.
Oder ist dieser Fall irgendwie in der Zeitdifferenz enthalten und führt
nur bei der direkten Frequenzmessung zu Problemen?
Das Umschalten von Flanken ist immer problematisch. Wie Du es genau
gemacht hast, ist ja nicht zu sehen.
Wenn Du schon alles mit einem Timer erledigen möchtest (meine Empfehlung
wäre ein passender STM32 mit ausreichend Timern), dann würde ich mit
beiden Flanken einen Capture-Interrupt auslösen und den Wert je nach
aufgetretener Flanke in zwei separaten Variablen summieren. Das
Verhältnis dieser Variablen ergibt dann das Tastverhältnis.
Alternativ können ein paar Timer die Funktion "Capture+Clear", mit der
die Pulsweite einer Periode erfaßt werden kann. Wie weit man dort mit 16
Bit Registern auskommt hängt von den Anforderungen und dem Vorteiler des
betreffenden Timers ab.
Ansonsten kann ich empfehlen, passende breakpoints zu setzen und Flags
und Register auf plausible Werte zu prüfen.
Hallo Michael (m.n.)
Danke für deine Antwort.
Der Vorteil der Verwendung mehrerer Timer wäre doch, dass man keine
Umschaltung der Flanken benötigt, richtig? Da immer 2 Kanäle pro Eingang
benutzt werden können und so die Flanken für die DC Messung nicht
umgeschaltet werden müssen, sondern je Kanal fest eingestellt sind.
Man muss dabei natürlich noch auf die Verteilung achten, also es können
nur Kanal 1&2 und Kanal 3&4 entsprechend gekoppelt werden, so dass man
dann pro Timer an 2 Frequenzeingänge die DutyCycle Messung nutzen kann.
Oder gibt es weitere Vorteile? Vielleicht noch die individuelle
Anpassung des Vorteilers bei sehr hohen Frequenzen.
Leider sind die anderen Timer bei mir bereits belegt (PWM).
Zu "Capture&Clear" habe ich beim STM32F105 und Timer1 nichts gefunden.
Gruß
Bernd
Das Umschalten der Flanken mache ich durch direktes setzen des
Registers.
Hallo Michael,
müsstest du im Update Interrupt nicht eigentlich auch den oben
beschriebenen Sonderfall betrachten? Also wenn beide Flags quasi
gleichzeitig auftreten, aber der Update Interrupt zuerst ausgeführt wird
und der Zählerwert >0x8000 ist. Dann muss noch der alte Overflowwert für
die Rechnung genommen und der alte Wert auch gespeichert werden.
Natürlich muss der globale Overflowzähler trotzdem einen hoch gezählt
werden.
Da das Auslesen des CCRx Registers implizit das CC Flag zurück setzt,
muss man hier aber aufpassen. Es wird dann nicht mehr der CC Interrupt
ausgeführt.
Bei 100 oder 20 Messungen pro Sekunde bekomme ich immer mal wieder einen
positiven und einen negativen Ausreißer. Das passt zu dem oben
beschriebenen Sonderfall. Bei größerer Messzeit ist das vermutlich aber
vernachlässigbar.
Bei direkter Frequenzmessung muss dieser Sonderfall aber auf jeden Fall
beachtet werden!