Hallo mal wieder, ich möchte ein PWM-Signal eines RC-Empfängers auf meinem STM32F4 einlesen. Dafür habe ich einen hochzählenden Timer mit zwei Input-Captures (Rising, Falling) und einem Output-Compare erzeugt. Der Timer läuft nach 15ms über. Ich habe es mir so vorgestellt, dass bei einer steigenden Flanke in den Timer-Interrupt gesprungen wird, ebenso bei einer fallenden Flanke. Zusätzlich läuft das Output-Compare im inaktiven Modus und zählt bis 3ms hoch um dann auch in den Interrupt zu springen. Das OutputCompare nutze ich zur Erkennung eines neuen PWM-Blocks, welche 20ms lang sind und mit einem abschließenden PWM-Pulse >= 4ms erkenntlich ist. Läuft der Timer über, also 15ms ohne die anderen Bedingungen, wurde kein vernünftiges Signal erkannt. Durch den SlaveModeReset setze ich den Timer bei jeder Rising-Edge zurück. Die eigentliche Auswertung des Signals erfolgt dann über die Interrupt-Routine. Insgesamt funktioniert es noch nicht so richtig, erstmal stelle ich aber fest das mein Problem schonmal daran liegt, dass der Timer überläuft (15ms) obwohl durch den SlaveModeReset doch bei jedem Rising-Edge der Timer resetet werden sollte. Das passiert anscheinend aber nicht, da regelmäßig ein "No Signal long time" detektiert wird.(Siehe Output.txt) Ich freue mich wie immer über jede Antwort die mir irgendwie weiterhelfen könnte. Ach ja und ich möchte das Signal nicht per "einfacher" Abtastung oder PWM_Input einlesen. Ich möchte jetzt gerne wissen wo das Problem liegt und nicht nur das Problem "irgendwie" lösen. Es sei denn ist gibt konkrete Gründe weshalb meine Variante schlecht ist :) Meine PLL-Config: PllM = 8 PllN = 336 PllP = 2 PllQ = 7 HSE_Value(8MHz) / 8 = 1MHz -> 1Mhz * 336 / 2 = 168 MHz (SysCLK) 1Mhz * 336 / 7 = 48 MHz (USB,SDIO,RNG) SysCLK(168MHz) / 4 = 42MHz (APB1) APB1(42MHz) * 2 = 84MHz (Tim2,3,4,5,6,7,12,13,14) SysCLK(168MHz) / 2 = 84MHz (APB2) APB2(84MHz) * 2 = 168MHz (Tim1,8,9,10,11) Viele Grüße, Florian
Vom Prinzip her würde ich bei Beginn des Signals den Timer reseten, oder Wert speichern und erst jetzt Capture scharf schalten. Beim nächsten Wechsel kommt das Capture und du kannst die Pulslänge bestimmen. Wenn die Pwm Periodenlänge unbekannt ist, wertet man den Zähler beim nächsten Beginn oder nimmt ein 2 Capture.
Aber was spricht gegen meine Variante. Sie sollte ja eigentlich auch so funktionieren...
Florian K. schrieb: > Aber was spricht gegen meine Variante. Sie sollte ja eigentlich > auch so > funktionieren... Sollte, sollte, Witwe Bolte.
EitelSonnerschein schrieb: > Florian K. schrieb: > >> Aber was spricht gegen meine Variante. Sie sollte ja eigentlich >> auch so >> funktionieren... > > Sollte, sollte, Witwe Bolte. Ja von der Theorie dahinter "sollte" es funktionieren. Nur meine praktische Umsetzung ist anscheinend gescheitert, nun ist meine Frage: An welcher Stelle? Konkret wäre erst einmal sehr interessant zu wissen, weshalb vor jedem Rising-Inputcapture (bzw. nach jedem Falling-InputCapture) auch das Update-Flag gesetzt ist, ich dachte das wird nur beim Überlauf des Timers(15ms) gesetzt?! Also im Grunde nie solange ein InputCapture (innerhalb der 15ms) erkannt wird, da dann der Timer doch automatisch au Null gesetzt wird! So sollte das Signal ungefähr aussehen: <----------------20ms-----------------> _|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-----|_ 1 2 3 4 5 6 7 8 9
Ich habe gerade eine Passage in der ApplicationNote AN4013.pdf gelesen: "As the buffered registers (ARR, PSC, CCRx) need an update event to be loaded with their preload values, set the URS (Update Request Source) to 1 to avoid the update flag each time these values are loaded. In this case, the update event is only generated if the counter overflow/underflow occurs " Gibt es hierfür eine StandardLibraryFunction, oder steckt diese Funktion schon irgendwie mit drin? Das würde mein Problem erklären
Hallo nochmal, bitte bitte bitte, kann sich irgendjemand nochmal meinem Problem annehmen?! Ich verzweifele langsam. Durch die Zeile:
1 | /* Configures the TIM3 Update Request Interrupt source (SETS the CR1->URS bit)*/
|
2 | TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Regular); |
verhindere ich nun schon einmal das bei jedem Rising-Event auch ein update-event generiert wird. Nun wird also kein Überlauf des Timer3 mehr erkannt, solange das PWM-Signal anliegt! Mein Problem ist aber, dass die Interrupt-Routine anscheinend nur bei einem Rising-Event betreten wird und dann gleichzeitg auch immer ein Falling-Event bereits eingetreten ist. Das ist meine aktuelle Bluetooth-Ausgabe: ... --------------------------------------------- -RISING-EVENT- sumLength: 4512 -OUTPUTCOMPARE-RESET- 3ms has gone: Reset long Pulse-timer -FALLING-EVENT- PulseLength: 2999 -OUTPUT-COMPARE->----------- Long Pulse captured ----------- --------------------------------------------- ... Wobei die gestrichelte Linie bei jedem Aufruf des TIM3_IRQHandler auftritt. eigentlich erwarte ich also folgendes: ... --------------------------------------------- -RISING-EVENT- sumLength: 4512 -OUTPUTCOMPARE-RESET- 3ms has gone: Reset long Pulse-timer --------------------------------------------- -FALLING-EVENT- PulseLength: 2999 --------------------------------------------- ... Wenn ich in TIM3_IRQHandler aus der Abfrage:
1 | /* Falling ------------------------------------------------------------------*/
|
2 | if((TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)) |
3 | {
|
folgendes mache:
1 | /* Falling ------------------------------------------------------------------*/
|
2 | else if((TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)) |
3 | {
|
Tritt dieser Teil, also "Falling-Event" überhaupt nicht mehr auf. Das heißt, bei jedem betreten von TIM3_IRQHandler gibt es ein Rising-Event!!! Ich habe nochmal die beiden interessanten Code-Ausschnitte angehangen. Bitte bitte helft mir :/ Viele Grüße, Florian
Hi, ich kann dir da leider nicht helfen, da ich damit noch nie gearbeitet habe. Aber hier ein Link, wo zumindest ein PWM Signal mit Hilfe von Timern ausgelesen wird. Vielleicht hilft der Code dir. http://mikrocontroller.bplaced.net/wordpress/?page_id=2125 Liebe Grüße, Jan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.