Hallo, ich versuche ein PWM-Signal mithilfe des STM32 auszuwerten. Dazu lege ich am PIN F0 (EXTI0-line) ein 1000us Signal an. Ich nutze dabei diesen PIN als Interrupt Eingang (RISING EDGE). Sobald der Interrupt ausgelöst wird springt er in den "void EXTI0_IRQHandler(void)". In dieser Interrupt Routine werte ich dabei die Flanke aus und schalte dann direkt den Interrupt "um" (von RISING auf FALLING und auch wieder umgekehrt). Ich setze vorher den TIM10 zurück (0) und lese beim nächsten Aufruf seinen Wert aus und speichere diesen direkt in ein Array (rx[7]). Später soll damit dann ein PPM Signal von einem Receiver ausgewertet werden. (Die gleiche Funktionalität habe ich bereits in einem Atmega328p implementiert und dort funktioniert es super und wirklich sehr genau. Ich verzichte dabei bewusst auf die Funktionalität des "INPUT CAPTURE", da damit kein Summensignal verarbeitet werden kann. Kommen wir nun zu meinem eigentlichen Problem: Das angelegte 1000us Signal ist sehr genau. Nun erhalte ich in meinem Array rx[0] extrem schwankende Werte: (Auszug aus der Console) 7895 9448 9448 7527 7527 7617 7617 7579 7579 7919 Dazu ist zu sagen, dass mein TIM10 mit einer Clock von 84Mhz betrieben wird und mit einem Prescaler von 9 auf 8.4Mhz runtertrimmt wird. Damit sollte ich bei 1000us auf einen Zählwert vom TIM10 von ca. 8400 kommen. Takt: 168MHZ mit HSE = 8Mhz. Board: STM32F429ZITx Disc1 Entwicklungsumgebung: Eclipse Debugger: openOCD Erstellt mit: CubeMX (Initialisierung) Jetzt wäre vielleicht noch der vollständige Code interresant ;-) https://codeshare.io/7m20E Ich bin mittlerweile echt ratlos, woran es liegen könnte. Könnte mir da jemand bei dieser Problematik weiterhelfen? Habt jetzt schon einmal vielen Dank!
>aus und schalte dann direkt den Interrupt "um" (von RISING auf FALLING und auch >wieder umgekehrt). >Die gleiche Funktionalität habe ich bereits in einem Atmega328p >implementiert und dort funktioniert es super Der STM32 kann das viel eleganter. Da brauchst Du nix umzuschalten. Hier ein Beispiel, wie ein RC Summensignal ausgewertet wird. Das Resultat aller Kanäle steht dann in rc_in_sigs[]:
1 | void TIM1_CC_IRQHandler(void) |
2 | {
|
3 | /* Clear TIM1 Capture compare interrupt pending bit */
|
4 | TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); |
5 | periode = TIM_GetCapture1(TIM1); |
6 | duty = TIM_GetCapture2(TIM1); |
7 | rc_captured(duty, periode); |
8 | }
|
1 | /**
|
2 | * IRQ callback function that decodes the duty and the
|
3 | * periode and sort it into the channel number
|
4 | */
|
5 | void rc_captured(uint16_t duty, uint16_t periode) { |
6 | |
7 | // If the periode is >600 (3ms), it is a new sequence
|
8 | if (periode > 600 ) { |
9 | rc_in_ix = 0; |
10 | }
|
11 | // Put the value into the next field of the array
|
12 | else if (rc_in_ix < 6) { |
13 | rc_in_sigs[rc_in_ix] = periode; |
14 | rc_in_ix++; |
15 | }
|
16 | |
17 | }
|
Quelle: https://github.com/gerdb/bumblecopter/blob/master/bumblecopter/src/it.c https://github.com/gerdb/bumblecopter/blob/master/bumblecopter/src/rc.c
Vielen Dank für den Hinweis :-) Werde ich direkt mal probieren. Aber rein zum Verständnis, Woran könnte die von mir beschriebene Ungenauigkeit liegen? Wird vielleicht der Interrupt selbst zu oft unterbrochen und damit der Zählwert schwankt? Gruß, Felix
>Aber rein zum Verständnis, Woran könnte die von mir beschriebene >Ungenauigkeit liegen? >Ich setze vorher den TIM10 zurück (0) und lese beim nächsten Aufruf >seinen Wert aus und speichere diesen direkt in ein Array (rx[7]). Man liest nicht den Timer aus, sondern immder das InputCapture Register. Das macht man auch beim ATMega so.
Ich bins nochmal: ich habe mir direkt mal die PWM INPUT MODE Geschichte angeschaut...nette Funktionalität. Dein Github Beispiel erscheint mir allerdings ein wenig verwirrend. Er initialisiert den Timer nicht so, wie es im Datenblatt angegeben ist: http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf "17.3.7 PWM input mode" Ich habe das ganze jetzt mal versucht umzusetzen, leider komme ich jetzt nicht mehr wirklich weiter. Eigentlich arbeite ich mit der HAL-Lib, dort finde ich die Einstellungen allerdings sehr wirr. Nun habe ich es mal mit direkten Registerzugriffen probiert (Abfolge laut Datenblatt):
1 | TIM1->CCMR1 |= (1 << 1); // select TI1 (CC1S = 01 [1,0]) |
2 | TIM1->CCER &= ~((1 << 1) | (1 << 3)); // select active polarity => rising edge (CC1S = 01 [1,0]) |
3 | |
4 | TIM1->CCMR1 |= (1 << 9); // select TI1 (CC2S = 10 [9,8]) |
5 | TIM1->CCER |= (1 << 5) | (1 << 7); |
6 | |
7 | TIM1->SMCR &= ~(1 << 5); // (TS = 101 6:4) |
8 | TIM1->SMCR |= (1 << 6) | (1 << 4); // (TS = 101 6:4) |
9 | |
10 | TIM1->SMCR &= ~((1 << 0) | (1 << 1)); |
11 | TIM1->SMCR |= (1 << 2); |
12 | |
13 | TIM1->CCER = 0x07; |
Was müsste nun noch getan werden, damit ich letztendlich meine Werte aus TIM1->CCR1 (Frequenz), TIM1->CCR2 (Duty Cycle) auslesen kann. Was auch sehr merkwürdig ist: wenn ich direkt ein Register beschreibe und mir direkt danach den Inhalt anzeigen lassen möchte, ist dieses "0"
1 | TIM1->CCER = 0x07; |
2 | trace_printf("Inhalt TIM1_CCER: %d", TIM1->CCER); |
Mache ich hier einen grundsätzlichen Fehler? Vielen Dank im Voraus!
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.