Um die PWM-Funktionen vom STM32F4 benutzen zu können, habe ich diese Library(s) geschrieben.
Der STM32F4 hat sehr viele Timer (14) und fast alle haben eine PWM funktion. Um den Aufwand etwas einzugrenzen hab ich mich für die 4 “General Purpose Timer” (TIM2, TIM3, TIM4, TIM5) entschieden, weil diese pro Timer 4 Kanäle besitzen.
Ich habe für jeden Timer eine eigene Library geschrieben, die bis auf die Namen der Funktionen und Variabeln gleich sind.
Somit kann man also, wenn man alle 4 Librarys benutzt und je 4 Kanäle aktiviert, maximal 16 PWMs realisieren.
Die Anzahl und Namen der PWMs die benutzt werden sollen, müßen im H-File deklariert und im C-File den entsprechenden Port-Pins zugeordnet werden.
(bei den Beispielen hab ich immer nur zwei PWMs pro Timer aktiviert)
Im H-File wird auch pro Timer die gewünschte Auflösung und die PWM-Frequenz eingestellt. Diese gilt dann für alle 4 Kanäle die mit diesem Timer betrieben werden.
Auch wird im H-File die Polarität vom PWM fesgelegt.
Beispielbild :
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : GPIO, TIM Benutzte Librarys : keine |
Enumerationen (für PWM mit TIM2) :
1 2 3 4 | typedef enum { PWM_T2_PB11 = 0, // PWM per TIM2 an PB11 PWM_T2_PA2 = 1 // PWM per TIM2 an PA2 }PWM_TIM2_NAME_t; |
Funktionen (für PWM mit TIM2) :
1 2 | void UB_PWM_TIM2_Init(void); // um den PWM mit TIM2 zu initialisieren void UB_PWM_TIM2_SetPWM(PWM_TIM2_NAME_t pwm, uint16_t wert); // zum einstellen eines PWM wertes |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | //-------------------------------------------------------------- // File : main.c // Datum : 26.03.2013 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.0 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der PWM-Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_pwm_tim4.h" #include "stm32_ub_adc1_single.h" int main(void) { uint16_t ad_wert; SystemInit(); // Quarz Einstellungen aktivieren // init vom ADC UB_ADC1_SINGLE_Init(); // Init vom PWM mit Timer4 // Settings vom H-File : // Auflösung = 8bit (0...255) // Frequenz = 1kHz // Kanal1 an PD12 // Kanal2 an PD14 UB_PWM_TIM4_Init(); // PD12 auf 25% einstellen UB_PWM_TIM4_SetPWM(PWM_T4_PD12,64); // PD14 auf 50% einstellen UB_PWM_TIM4_SetPWM(PWM_T4_PD14,128); while(1) { // AD-Wert an PA3 lesen ad_wert=UB_ADC1_SINGLE_Read_MW(ADC_PA3); // von 12bit in 8bit umwandeln ad_wert=(ad_wert>>4); // als PWM Wert an PD12 ausgeben; UB_PWM_TIM4_SetPWM(PWM_T4_PD12,ad_wert); } } |
Hier die Library zum Download :
Hier der komplette CooCox-Projektordner zum Download :
Hallo,
vielen Dank für diese und alle anderen Libs! Einige benutze ich schon erfolgreich. Bei dieser habe ich jedoch zum ersten Mal ein Problem:
Die PWM an PD12 hat immer 25%, egal welchen Wert ich einstelle:
// PD12 auf 25% einstellen
UB_PWM_TIM4_SetPWM(PWM_T4_PD12,64);
In der nächsten Zeile für PD14 funktioniert’s perfekt!
Außerdem bekomme ich es nicht hin, die 2 weiteren PWMs zu aktivieren. Ich habe im h-File eingetragen:
typedef enum
{
PWM_T4_PD12 = 0, // PWM per TIM4 an PD12
PWM_T4_PD14 = 1, // PWM per TIM4 an PD14
PWM_T4_PD13 = 2, // PWM per TIM4 an PD13
PWM_T4_PD15 = 3 // PWM per TIM4 an PD15
}PWM_TIM4_NAME_t;
#define PWM_TIM4_ANZ 4 // Anzahl von PWM_TIM4_NAME_t
Aber PD13 und PD15 bleiben tot. Was muss ich noch tun?
Nochmals vielen Dank!
das H-File hast du richtig geändert. Aber im C-File müssen die beiden neuen PWMs auch noch eingetragen werden.
probier mal aus ob damit der Fehler weg ist und alle 4 PWMs funktionieren.
Super, danke!
Jetzt kommt aus allen 4 Pins etwas raus
Allerdings ist die PWM auf PD12 noch immer nicht einstellbar, sondern fest bei 25%.
Die anderen 3 lassen sich prima einstellen.
du benutzt aber nicht das Beispielprogramm von hier oder ? …weil da wird PD12 in der while ständig mit einem Wert beschrieben !!
Aaaaah!
Wer guckt denn schon in die while?
Oh man, danke!
kann sein, dass du 4 PWMs für einen Quadcopter brauchst?
Wenn ja, wie ist der Stand bei Dir?
zur Info:
Wenn mann mehrere PWM-Timer gleichzeitig benutzen möchte, meckert der Compiler.
Die internen Funktionen werden in jeden File neu erstellt: P_PWM_InitIO(); P_PWM_InitTIM();
Ich habe die Funkionen jeweils mit einem Index des Timers versehen, so dass kein Name mehr doppelt vorkommt, es scheint zu laufen.
Muss ich etwas besonderes beachten wenn ich Pf9 /Tim14 Channel1 benutzen will?
Ok funktioniert Problemlos.
Wichtig ist bei der Nutzung mehrerer Timer die Funktionsnamen anzupassen.
Hallo admin_ub,
ich wollte zwischen Demo_84_SPI_LIS3DSH und Demo_25_PWM ein Kombination erstellen. Ich habe dir “neueren” Header-Dateien eingepflegt aber er wollte dann nicht mehr compilieren.
Mein Ziel ist je nach Neigung des Sensors den Tastverhältnis der unterschiedlichen 4PWM zu ändern.
Auf eine Antwort freue ich mich.
Danke!
mit der Fehlermeldung “er wollte dann nicht mehr compilieren” kann ich nichts anfangen.
1. Neues “leeres” projekt anlegen
2. Files von LIS3DSH, SPI1, PWM hinzufügen.
3. Compiler darf keinen Fehler melden
4. Erst jetzt eigenen Code hinzufügen
Hallo,
wie bekomme ich (bei PE10) z.B. den “TIM1_CH_2N” zum laufen?
Der “TIM1_CH_2″ (PE11) funktioniert einwandfrei.
Ich möchte quasi 2 PWM-Signale erzeugen, die um 180° versetzt sind, um ein Encoder-Signal zu simulieren.
Vielen Dank für die baldige Antwort
Gruß Jens
den Pin in der PWM-Struktur eintragen, damit er als GPIO konfiguriert wird
in der OCInitStructure müssen dann noch zwei Werte gesetzt werden :
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
polarität entweder “TIM_OCNPolarity_High” oder “TIM_OCNPolarity_Low”
das “TIM_CtrlPWMOutputs(TIM1, ENABLE);” darf bei Timer-1
auch nicht vergessen werden.
Hinweis : Encoder-Signale sind nicht invertiert sondern
90° Phasenverschoben
vielen Dank für die schnelle Antwort.
Ja das meinte ich, die Phasenverschiebung. Habe mich einfach bescheuert ausgedrückt.
Ist deine Lösung für die Phasenverschiebung?
Gruß Jens
mach es anders. Nimm das original Beispiel von hier mit Timer-2 per CH3 und CH4. Dann ändere bei allen Kanälen den Timer-Mode von “PWM” in “Toggle” also die Zeilen :
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
damit ergeben sich zwei Rechtecksignale,
deren Tastverhältnis immer 50/50 ist aber
die Phasenlage untereinander lässt sich über die
Pulswerte einstellen.
Stell CH4 auf einen Pulswert von 1 und CH3
auf einen Pulswert von 128 dann sind sie um 90°
versetzt.
Hallo,
Danke!
Ich habe es mit der PWM nun doch zum Laufen gebracht.