Guten Tag,
ich versuche verzweifelt auf einen STM32F103 eine Frequenzmessung zu
realisieren.
Dabei bin ich jetzt soweit das die Messung einige Stunden einwandfrei
funktioniert jedoch ab und zu (in 2 Stunden ca einmal) 1. falschen Wert
liefert und dann wieder perfekt passt.
Ich will jedoch das die Messung zu 100% richtig ist.
Wie ist das Verhalten der Interrupt bei so einem Mikrocontroller?
Ich habe zwei Interrupts die ich auswerte zum einem den
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
zur Overflow Erkennung.
Und zum anderen
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
für Capture Messung.
Was passiert wenn wärend des Capture Interrupt der Overflow Interrupt
erreicht wird?
Wird da der erste Interrupt unterbrochen?
Oder wird der erste Inerrupt beendet und dann sofort in den zweiten
gesprungen?
Danke für die Hilfe
Calon schrieb:> Wird da der erste Interrupt unterbrochen?> Oder wird der erste Inerrupt beendet und dann sofort in den zweiten> gesprungen?
Das kommt darauf an wie du die Interrupt Prioritäten gesetzt hast.
Calon schrieb:> Dabei bin ich jetzt soweit das die Messung einige Stunden einwandfrei> funktioniert jedoch ab und zu (in 2 Stunden ca einmal) 1. falschen Wert> liefert und dann wieder perfekt passt.
Riecht nach einen Integer-Überlauf bzw. falscher Berechnung der
Differenz von zwei Zählwerten.
Calon schrieb:> zur Overflow Erkennung
Was passiert dort? Wird ein Zaehler weitergezaehlt? Also die 16 Bit
aufgebohrt?
Dann muesstest du dem Overflow die hoehere Prioritaet geben und nach dem
Lesen beider Zaehlerteile nochmal den ersten Wert ruecklesen um
sicherzugehen, dass nicht zwischendurch ein Overflow stattfand.
Kevin M. schrieb:> Das kommt darauf an wie du die Interrupt Prioritäten gesetzt hast.
Hmm ich habe den Globalen Interrupt Tim4 aktiviert.
Kann man für beide Interrupt eine Priorität setzen?
Maxe schrieb:> Was passiert dort? Wird ein Zaehler weitergezaehlt? Also die 16 Bit> aufgebohrt?
Ich zähle die Overflows seit der ersten fallenden Flanke.
Bei der zweiten fallenden Flanke übergebe ich beide Zählerstände und die
Anzahl der erfolgten Overflows der mein Loop, wo ich dann die Frequenz
ausrechne
Maxe schrieb:> Dann muesstest du dem Overflow die hoehere Prioritaet geben und nach dem> Lesen beider Zaehlerteile nochmal den ersten Wert ruecklesen um> sicherzugehen, dass nicht zwischendurch ein Overflow stattfand.
Kannst mir das nochmal erklären? Verstehe nicht wie du das meinst.
Danke für die Hilfe
Calon schrieb:> Maxe schrieb:>> Dann muesstest du dem Overflow die hoehere Prioritaet geben und nach dem>> Lesen beider Zaehlerteile nochmal den ersten Wert ruecklesen um>> sicherzugehen, dass nicht zwischendurch ein Overflow stattfand.>> Kannst mir das nochmal erklären? Verstehe nicht wie du das meinst.
Was passieren kann: Der Counter kommt zum Overflow (d.h. fängt von 0
an), aber der Overflow-Interrupt konnte noch nicht triggern, weil der
Capture-Interrupt gerade läuft. Der Overflow-Zähler hat also den alten
Stand, obwohl der Overflow schon passiert ist und der gelesene
Counterwert schon in der neuen Runde ist.
Um das zu vermeiden muss also der Overflow-Interrupt eine höhere
Interruptpriorität haben, dann unterbricht er den Capture-Interrupt
wärend der Abarbeitung und kehrt anschließend zurück in den
Capture-Interrupt. Dann kann es aber passieren, dass der
Overflow-Interrupt genau dann zuschlägt, wenn man den Counter-Wert
gelesen hat, aber den Overflow-Wert noch nicht. Oder andersrum, je
nachdem, was man zuerst macht.
Um das Problem abzufangen, kann man den erstgelesenen Wert nochmal
abfragen. Hat er sich nicht geändert, waren beide Werte in Ordnung. Hat
er sich in der Zwischenzeit geändert, nimmt man den zweiten Wert und
liest den nur einmal gelesenen Wert nochmal aus. Die beiden Werte
stimmen dann definitiv, weil in so kurzer Zeit keine 2 Overflows
auftreten können.
Kann aber sein, dass es auch noch eine einfachere Lösung gibt...
Maxe schrieb:> Um das zu vermeiden muss also der Overflow-Interrupt eine höhere> Interruptpriorität haben, dann unterbricht er den Capture-Interrupt> wärend der Abarbeitung und kehrt anschließend zurück in den> Capture-Interrupt. Dann kann es aber passieren, dass der> Overflow-Interrupt genau dann zuschlägt, wenn man den Counter-Wert> gelesen hat, aber den Overflow-Wert noch nicht. Oder andersrum, je> nachdem, was man zuerst macht.>> Um das Problem abzufangen, kann man den erstgelesenen Wert nochmal> abfragen. Hat er sich nicht geändert, waren beide Werte in Ordnung. Hat> er sich in der Zwischenzeit geändert, nimmt man den zweiten Wert und> liest den nur einmal gelesenen Wert nochmal aus. Die beiden Werte> stimmen dann definitiv, weil in so kurzer Zeit keine 2 Overflows> auftreten können.>> Kann aber sein, dass es auch noch eine einfachere Lösung gibt...
Danke für die Erklärung.
Wie kann ich die Priorität einstellen?
Calon schrieb:> Habe in der Einstellung hier nichts gefunden für die einzelnen Interrupt> von Tim4
Timer 4 hat beim F103 nur einen Interrupt. Beide Events gehen bei dir
über den Timer 4, oder? D.h. vermutlich werden die über die HAL
unterschieden (wie gesagt, kenne mich da nicht aus). Da es in Hardware
nur einen Handler gibt, kann man nicht per Hardware priorisieren lassen.
Vermutlich kannst du den (Timer-)Interrupt im Capture-Event wieder
aktivieren bevor du den Counter ausliest, dann könnte der Overflow
"reingrätschen" (dabei Vorsicht!).
Oder du nimmst einen getrennten/zweiten Timer als Counter.
Oder du nimmst Timer 1, der hat getrennte Interrupts für Update
(=Overflow) und Capture.
Maxe schrieb:> Um das zu vermeiden muss also der Overflow-Interrupt eine höhere> Interruptpriorität haben,
Schlechte Lösung. Beide Interrupts sollten die gleiche Priorität
besitzen.
Calon schrieb:> Kannst du mir helfen eine Lösung zu finden?
Für den F407 findest Du Code für Timer9 (void
TIM1_BRK_TIM9_IRQHandler(void)) im gezeigten Beispiel:
Beitrag "reziproker Frequenzzähler mit STM32F4Discovery"
Es ist wichtig, daß der Überlauf erst zum Schluß der ISR bearbeitet
wird.
m.n. schrieb:> Beide Interrupts sollten die gleiche Priorität besitzen.
Wie bekommt er dann im Capture-Event mit, dass ein Überlauf gerade
stattgefunden hat? Der Zähler läuft ja trotzdem weiter, also von vorne
los, auch wenn der Überlauf noch nicht verarbeitet wurde.
Maxe schrieb:> Wie bekommt er dann im Capture-Event mit, dass ein Überlauf gerade> stattgefunden hat? Der Zähler läuft ja trotzdem weiter, also von vorne> los, auch wenn der Überlauf noch nicht verarbeitet wurde.
Den Link zum Code habe ich genannt und ebenso die Routine, wo die
Interupts verarbeitet werden. Da kannst Du die Antwort auf Deine Frage
finden.
Das Prinzip der Timererweiterung ist hier erläutert:
Beitrag "AVR Timer mit 32 Bit"
Optimal ist es, wenn beide Interrupts die gleiche Priorität haben, also
sich nicht gegenseitg unterbrechen können.
Calon schrieb:> Eine ganz doofe Frage, ist der zugriff auf int32 Variablen auf dem> STM32F103 atomar möglich?
Gegenfrage: Warum heißt das Teil STM32 und nicht STM8?
Oder anders formuliert: man muß explizit angeben, wenn man die 32 Bit
Variablen nicht atomar ansprechen möchte.
m.n. schrieb:> Gegenfrage: Warum heißt das Teil STM32 und nicht STM8?> Oder anders formuliert: man muß explizit angeben, wenn man die 32 Bit> Variablen nicht atomar ansprechen möchte.
Ja wahr mir nur nicht mehr zu 100% sicher.
Und man kann nicht Atomar zugreifen? Will man das manchmal?
Danke für die Hilfe.
Peter D. schrieb:> Das Prinzip der Timererweiterung ist hier erläutert:>> Beitrag "AVR Timer mit 32 Bit">> Optimal ist es, wenn beide Interrupts die gleiche Priorität haben, also> sich nicht gegenseitg unterbrechen können.
Danke Peter für deinen Code.
Ist Deine Methode auch für eine Capture Frequnezmessung anwendbar?
Sorry wenn ich dumm frage aber ich möchte ja lernen.
peter dannegger schrieb:> Die nächste Hürde ist dann, wenn gerade dabei ein Overflow auftritt,> ist zwar selten, aber es passiert. Mancher, der mal einen> Frequenzzähler so aufgebaut hat, wird gemerkt haben, daß bei bestimmten> Werten die Anzeige verrückt spielt und große Sprünge macht. Genau das> ist dann so ein nicht berücksichtigter Overflow.
Mein Problem ist das ich sporadisch einen Overflow Interrupt zu viel
habe.
Und ich nicht verstehe wo dieser her kommt.
Calon schrieb:> Mein Problem ist das ich sporadisch einen Overflow Interrupt zu viel> habe.
Manche ARM-CPUs haben das Problem, daß Signale mehrere Takte brauchen,
ehe sie aktualisiert werden.
Wird das Pending-Flag erst am Ende des Handlers gelöscht, kann die Logik
es noch als gesetzt erkennen und einen neuen Interrupt auslösen.
Pending-Flags sollten daher sofort am Anfang des Handlers gelöscht
werden.
Habe mal meinen Code etwas aussortiert und das relevante in eine c Datei
geklatscht.
Vielleicht hat ja jemand Lust drüber zu gucken.
Habe ja sehr überschaubaren einfachen Laienhaften Code geschrieben.
Peter D. schrieb:> Pending-Flags sollten daher sofort am Anfang des Handlers gelöscht> werden.
Was meinst du mit Pending-Flags ?
Danke Euch Allen!
Calon schrieb:> Was meinst du mit Pending-Flags ?
Ich benutze einen LPC4357. Da muß ich in jedem Interrupthandler das
ensprechende Pending Flag löschen, z.B.:
1
voidTIMER3_IRQHandler(void)
2
{
3
Chip_TIMER_ClearMatch(LPC_TIMER3,0);// Clear Flag for Match 0
Peter D. schrieb:> Calon schrieb:>> Was meinst du mit Pending-Flags ?>> Ich benutze einen LPC4357. Da muß ich in jedem Interrupthandler das> ensprechende Pending Flag löschen, z.B.:void TIMER3_IRQHandler(void)> {> Chip_TIMER_ClearMatch(LPC_TIMER3, 0); // Clear Flag for Match> 0> trg_toggle = !trg_toggle;> Chip_GPIO_SetPinState(LPC_GPIO_PORT, GPIOM_TRGOUT, trg_toggle);> }
Soweit ich weiß sollte das die HAL übernehmen.
Danke für die Hilfe
Irgendwie finde ich nicht warum ich sporadisch einen Overflow Interrupt
zu viel.
Wobei ich im Capture Interrupt und nur da die Overflows an die Main
übergebe.
Hat jemand eine Idee wie es zu diesem verhalten kommen kann?
Ich verzweifle.
War da nicht was mit sporadischen Interrupts bei bestimmten China
Klonen? Ich meine da mal was gelesen zu haben. Der Workaround war, in
der ISR immer die Peripherie zu fragen, ob sie einen IRQ ausgelöst hat.
Wenn nicht, dann einfach return.
Stefan ⛄ F. schrieb:> War da nicht was mit sporadischen Interrupts bei bestimmten China> Klonen? Ich meine da mal was gelesen zu haben. Der Workaround war, in> der ISR immer die Peripherie zu fragen, ob sie einen IRQ ausgelöst hat.> Wenn nicht, dann einfach return.
Echt sowas gibt es?Wie kann sich feststellen ob ich einen China Clone
habe?
Kannst du mir sagen wie genau du das mit dem Workaround meinst?
Danke für die Hilfe.
Calon schrieb:> Echt sowas gibt es?Wie kann sich feststellen ob ich einen China Clone> habe?
Angeblich geht das mit dem angehängten Programm. Das hat hier mal jemand
empfohlen. Allerdings war man sich über die Interpretation der
Ergebnisse uneinig. Es gibt wohl ein paar Anzeichen für Fakes, aber
nicht alle fallen auf diesem Weg auf.
Du kannst ja mal die Ausgabe hier posten.
moin,
zum ChinaClown siehe:
Beitrag "STM32F103C8T6 - Fälschung von ST bestätigt"
Beitrag "reziproker Frequenzzähler mit STM32F4Discovery"
Dort wird mindesten STM32F4 verwendet. Ist nicht unbedingt mit F1
vergleichbar.
Mein Problem ist genau andersherum: spardisch habe ich ein paar
Overflows zu wenig.
In der ISR frage ich die Bits ab, so wie Stefanus vorgeschlagen hat.
Meine Messmethode ist: Mit Timer eine Freq. erzeugen ( reine HW ) und
dies messen.
Sollte die PLL jittern geht das auf beide Frequenzen.
Beispiel: Meine Messung ist 5,6782337KHz.
Sporadisch aber 5,700xxxKHz, also 22Hz zuhoch.
Bei Messung von 1,2340390KHz steht, aber auch dort alle paar Minuten
1,238xxKHz.
Also weitersuchen.
VG
Peter
Calon schrieb:> Wie ist das Verhalten der Interrupt bei so einem Mikrocontroller?> Ich habe zwei Interrupts die ich auswerte zum einem den>> void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)> zur Overflow Erkennung.> Und zum anderen> void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
Also erstens: Der Controller unterbricht die laufende Arbeit und springt
zu der Adresse, die an der für diesen Interrupt zuständigen Stelle im
Felde der Interruptvektoren steht. Was ab da gemacht wird, ist
Obliegenheit des Programmierers. Da du offenbar die HAL-Bibliotheken von
ST benutzt, müßtest du (sofern du die Quellen dafür hast) dort
nachschauen.
Und zweitens: Was du angeführt hast sind dem Anschein nach
Callback-Funktionen. Das sind keine Interrupthandler, sondern Zeugs, was
der oder die Interrupthandler bei Bedarf von sich aus aufrufen. Was da
zuvor so alles abgeht, kannst du wiederum nur durch Lesen der Quellen
von ST ergründen.
W.S.
@w.s.
mag ja alles sein, aber bei mir wird das direkt ohne HAL abgearbeitet.
Der Messfehler/Zeitabstand hängt bei mir von der zu messenden Frequenz
ab.
@Calon
Kannst Du das bestätigen?
VG
Peter
Calon schrieb:> Vielleicht hat ja jemand Lust drüber zu gucken.
Vorteiler 71? Periode 49999?
Was soll das?
Pieter schrieb:> Dort wird mindesten STM32F4 verwendet. Ist nicht unbedingt mit F1> vergleichbar.
Die Timer sind in den Grundfunktionen vergleichbar.
Calon schrieb:> Vielleicht hat ja jemand Lust drüber zu gucken.
Ich sehe da keine Behandlung, wenn ein Overflow passiert, während man
gerade im Capturehandler ist.
Schau Dir mal meinen Link an. Da wird das berücksichtigt.
Ich setze den Zähler auch nie zurück, sondern merke mir den Startwert
und bilde die Differenz. Das Rücksetzen ist nämlich auch kritisch.
Pieter schrieb:> hallo Michael,> Dein Prog:> www.mino-elektronik.de> 2012-10-28>> macht bei mir auch sporadische Sprünge.
Welche Sprünge? Hattest Du nicht in Pascal programmiert?
Michael schrieb:
..Hattest Du nicht in Pascal programmiert?
Ja und?
In der Firma in C und zu Hause in Pascal.
Die Umsetzung ist doch nur 1:1.
Anzeige ist 1234,0389Hz, sporadisch aber 1249,7865Hz.
Mit einem STM32F103C8.
Wenn ich Zeit habe, baue ich das mit einem BlackPill ( STM32F413 ).
Ist die Verarbeitung des inputCapture wert Grundsätzlich falsch?
Habe ich das Prinzip schon falsch aufgespurt?
Ich bekomme Diese Debug Ausgabe
"pw_us= 62589, Frequenz = 15.98 Hz OV=1 b=12593 a=3 "
Das heißt Mein Zähler war beim Start auf 3, habe dann den Overflow
Counter genullt beim nächsten Capture war der Zähler auf 12593 und laut
den 79,43Hz die mein Funktionsgenerator ausspuckt darf kein Overflow
statt gefunden haben. Den overflow counter lese ich ja vor dem lesen des
Zählerstandes.
Pieter schrieb:> Anzeige ist 1234,0389Hz, sporadisch aber 1249,7865Hz.> Mit einem STM32F103C8.
Laß Dir mal die Zählerstände für Ereignisse und Zeit anzeigen.
> Die Umsetzung ist doch nur 1:1.
1:1 kann nicht sein. Der STM32F103 hat doch garkeinen Timer9.
Calon schrieb:> Was übersehe ich?
Du machst irgendetwas, hast aber kein Konzept!
Peter D. schrieb:> Ich sehe da keine Behandlung, wenn ein Overflow passiert, während man> gerade im Capturehandler ist.
Ich glaube das kann es sein Danke Peter
Calon schrieb:> Wie kann ich beim STM32F103 das Overflow Interruptflag löschen?
Schau sicherheitshalber beim richtigen Timer nach. Es würde mich bei ST
nicht überraschen, wenn das je nach Timer anders gemacht werden muss.
sehr
Stefan ⛄ F. schrieb:> Calon schrieb:>> Wie kann ich beim STM32F103 das Overflow Interruptflag löschen?>> Schau sicherheitshalber beim richtigen Timer nach. Es würde mich bei ST> nicht überraschen, wenn das je nach Timer anders gemacht werden muss.> sehr
Viel Dank
Also im Dattenblatt steht
Bit 9 CC1OF: Capture/Compare 1 overcapture flag
This flag is set by hardware only when the corresponding channel is
configured in input
capture mode. It is cleared by software by writing it to ‘0’.
0: No overcapture has been detected.
1: The counter value has been captured in TIMx_CCR1 register while CC1IF
flag was
already set
Warum erkennt das Atollic TrueStudio "CC1OF" nicht?
Calon schrieb:> Warum erkennt das Atollic TrueStudio "CC1OF" nicht?> TIM4->SR &= ~(1<<CC1OF);
Schau in die Header-Datei (stm32f101xb.h), wo die ganzen Register
definiert sind. Strg-Mausklick auf TIM4 sollte sie öffnen. In der Datei
suchst du dann nach "CC1OF".
1
/******************** Bit definition for TIM_SR register *******************/
Stefan ⛄ F. schrieb:> Calon schrieb:>> Warum erkennt das Atollic TrueStudio "CC1OF" nicht?>> TIM4->SR &= ~(1<<CC1OF);>> Schau in die Header-Datei (stm32f101xb.h), wo die ganzen Register> definiert sind. Strg-Mausklick auf TIM4 sollte sie öffnen. In der Datei> suchst du dann nach "CC1OF".> /******************** Bit definition for TIM_SR register> *******************/> ...> #define TIM_SR_CC1OF_Pos (9U)> #define TIM_SR_CC1OF_Msk (0x1U << TIM_SR_CC1OF_Pos)>> Folglich muss deine Code-Zeile so lauten:TIM4->SR &=> ~(1<<TIM_SR_CC1OF_Pos);> oder:TIM4->SR &= ~TIM_SR_CC1OF_Msk;> oder:CLEAR_BIT(TIM4->SR, TIM_SR_CC1OF_Msk)> Schau dir mal diese Makros (per Strg-Mausklick) an, ich finde sie> verbessern die Lesbarkeit des Quelltextes.
Guter Tipp! Danke!!!
Bei den Atmels 8Bittern war das alles vieeeeeeeeeeel einfacher.
Aber jede Reise beginnt mit dem ersten Schritt.
Und mit guter Unterstützung wird es wohl langsam werden hoffe ich!
Calon schrieb:> Bei den Atmels 8Bittern war das alles vieeeeeeeeeeel einfacher.> Aber jede Reise beginnt mit dem ersten Schritt.> Und mit guter Unterstützung wird es wohl langsam werden hoffe ich!
Dann schau dir doch mal meine Webseite zum Thema an. Ich hatte genau die
gleichen Schwierigkeiten beim Umstieg von AVR zu STM32. Alles war mir
dabei wichtig erschien, habe ich dort aufgeschrieben.
http://stefanfrings.de/stm32/index.html
Mit SPI habe ich mich allerdings auf diesen Controllern noch nicht
beschäftigt, dazu findest du dort keine konkreten Beispiele.
Stefan ⛄ F. schrieb:> Dann schau dir doch mal meine Webseite zum Thema an. Ich hatte genau die> gleichen Schwierigkeiten beim Umstieg von AVR zu STM32. Alles war mir> dabei wichtig erschien, habe ich dort aufgeschrieben.
Tolle Arbeit hast du da gemacht!
Irgendwie macht man ein großes Fass auf wenn man mit ST32 beginnt!
So nochmal ein Update zu meinem Problem.
Ich habe nun probiert aus dem Capture Interrupt raus den Overflow
Interrupt zu löschen. Aber der Erfolg hat sich nicht eingestellt.
Das Problem ist immer noch das wenn der Capture-A im bereich zwischen0-3
ist trotz löschen des Interrupt Flag Bit der Overflow Interrupt gezählt
wird.
Ist das Bit nicht das richtige?
TIM4->SR &= ~(1<<TIM_SR_CC1OF_Pos);
So allmählich bin ich am verzweifeln.
Ich würde empfehlen, es so zu machen, wie PeDa es verlinkt/erklärt hat.
D.h. der Overflowinterrupt wird nicht gelöscht, sondern kümmert sich
ganz normal ums Weiterzählen. Tritt aber der Fall auf, dass im
Captureinterrupt auch ein Overflow "eintrifft", dann berücksichtigt man
dort zwar den fehlenden Overflow, schriebt aber nicht in den
Overflowzähler. Nur der Overflowinterrupt ist dafür verantwortlich.
Warum der Overflowinterrupt bei dir trotz Löschen des Flags noch
aufgerufen wird, weiß ich auch nicht, könnte aber sein, dass die HAL im
Interrupthandler gleich alle Flags auswertet und dann die entsprechenden
Callbacks bedient. Wie gesagt gibt es nur einen Interrupthandler für
alle Timerinterrupts beim Timer 4.
Calon schrieb:> Ich habe nun probiert aus dem Capture Interrupt raus den Overflow> Interrupt zu löschen. [...]> Ist das Bit nicht das richtige?> TIM4->SR &= ~(1<<TIM_SR_CC1OF_Pos);
Eher nicht, du benötigst das Bit "UIF".