Hallo, ich möchte gerne ein PWM Signal mit einem STM32F4 erzeugen. Das Signal soll einen Frequenz von 50Hz haben und eine Puls von 1500µs länge. Hat jemand vielleicht einen Code-Ausschnitt für mich wo ein Timer Initalisiert und gestartet wird? Am besten wenn der Timer auch noch per DMA geladen wird. Moritz
Bei mein discovery board (STM32F100) lauft das mit Timer 1 in PWM mode (hat 4 Channels, damit kan men dan 4 verschiedene Servo-signale erzeugen). Timer lauft an 1 MHz (forteiler), zaehlt bis 19999 (= 20ms), dan fangt er wieder an. Die 4 channels stellt men dan ein auf 1000 bis 2000 (= 1 bis 2 ms). Auflosung ist dan 1µs. Code config Timer 1 : (GPIO und clock Timer 1 auch noch configurieren !)
1 | void Timer_Config(void) |
2 | {
|
3 | /* -----------------------------------------------------------------------
|
4 | TIM1 Configuration: generate 2 PWM signals with 2 different duty cycles:
|
5 | TIM1CLK = 24 MHz, Prescaler = 23, TIM1 counter clock = 1 MHz
|
6 | TIM1 ARR Register = 19999=> TIM1 Frequency = TIM1 counter clock/(ARR + 1)
|
7 | TIM1 Frequency = 50 Hz.
|
8 | TIM1 Channel1 pulse lenght = TIM1->CCR1 value gives servo between 1000 and 2000 µs
|
9 | TIM1 Channel4 pulse lenght = TIM1->CCR4 value gives servo between 1000 and 2000 µs
|
10 | ----------------------------------------------------------------------- */
|
11 | TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; |
12 | TIM_OCInitTypeDef TIM_OCInitStructure; |
13 | /* Time base configuration TIM1*/
|
14 | TIM_TimeBaseStructure.TIM_Period = 19999;//PWM freq. = 1MHz/20000 = 50Hz |
15 | TIM_TimeBaseStructure.TIM_Prescaler = 23;// Timer loopt aan 24 MHz/24 = 1MHz |
16 | TIM_TimeBaseStructure.TIM_ClockDivision = 0; |
17 | TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; |
18 | TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); |
19 | /* PWM1 Mode configuration: TIM 1, Channel1 */
|
20 | TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; |
21 | TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; |
22 | TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; |
23 | TIM_OC1Init(TIM1, &TIM_OCInitStructure); |
24 | TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); |
25 | /* PWM1 Mode configuration: TIM 1, Channel4 */
|
26 | TIM_OC4Init(TIM1, &TIM_OCInitStructure); |
27 | TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); |
28 | }
|
Hallo, viele Dank für das Beispiel. Hat jemand viellecht noch ein Beispiel für STM32F4? Moritz
Hallo, hat jemand vielleicht einen Kompletten source code, wo ein TIMER Initalisiert wird? Weiß jemand wovon der TIMCLK1 abgeleitet wird? Moritz
Beim F1er gabs in der Firmwarebibliothek Beispiele für alle Peripherieeinheiten, beim F4er nicht? Andersrum wird hier ein Schuh draus: zeige, was du bisher geschafft hast und wir helfen dir Fehler zu finden. Für dich was schreiben wird hier niemand! Aber zwischen den Zeilen lese ich eine gewisse Unlust zur selbstständigen Arbeit heraus...
Hallo, ja ich möchte schon selber etwas programmieren doch leider weiß ich noch nichts über die Timer (Deshalb frage ich ja). Am einfachsten für mich ist es aus fertigem code zu lernen. Bei der Lib sind auch einige Beispiele dabei dabei, allerdings erklärt die nicht woher der Takt der Timer kommt, was die verschidenen Vorteile Bedeuten und wozu die gut sind usw... . In den Reference Manual und dem Datasheet werde ich auch nicht schlauer. Moritz
Hi Moritz mir ist das Benutzen eines Timers heute erfolgreich mit dem STM32F4 Board gelungen. Das folgende Beispiel nutzt TIM4 mit PWM. Das "Ergebnis" wird auf der grünen onboard LED ausgegeben. Die LED wird entsprechend heller und dunkler.
1 | #include "stm32f4xx_conf.h" |
2 | |
3 | #define MOTORPWMTIMER TIM4
|
4 | #define MOTORPWMTIMCLOCK RCC_APB1Periph_TIM4
|
5 | #define MOTORPWMPORTCLOCK RCC_AHB1Periph_GPIOD
|
6 | #define MOTORPWMAF GPIO_AF_TIM4
|
7 | #define MOTORPWMPORT GPIOD
|
8 | #define MOTORPWMBIT GPIO_Pin_12
|
9 | #define MOTORPWMTIMBIT GPIO_PinSource12
|
10 | |
11 | |
12 | // Private typedefs ----------------------------------------------------------
|
13 | GPIO_InitTypeDef GPIO_InitStructureLED; |
14 | GPIO_InitTypeDef GPIO_InitStructureTimer; |
15 | TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; |
16 | TIM_OCInitTypeDef TIM_OCInitStructure; |
17 | |
18 | |
19 | // Private variables ---------------------------------------------------------
|
20 | uint32_t TimerCounterClock = 0; |
21 | uint32_t TimerOutputClock = 0; |
22 | uint16_t PrescalerValue = 0; |
23 | uint32_t PulseDurationInMicroSeconds = 0; |
24 | |
25 | int i; |
26 | |
27 | |
28 | // the prototypes ------------------------------------------------------------
|
29 | int main(void); |
30 | |
31 | // Timer init for PWM
|
32 | void TimerInit(void); |
33 | |
34 | void Delay(__IO uint32_t nCount); |
35 | |
36 | |
37 | int main(void) |
38 | {
|
39 | /*!< At this stage the microcontroller clock setting is already configured,
|
40 | this is done through SystemInit() function which is called from startup
|
41 | file (startup_stm32f4xx.s) before to branch to application main.
|
42 | To reconfigure the default setting of SystemInit() function, refer to
|
43 | system_stm32f4xx.c file
|
44 | */
|
45 | |
46 | // /dev/tty.usbserial-A900J1T0
|
47 | |
48 | // call my new USART init
|
49 | usartInit(); |
50 | |
51 | |
52 | // call timer init for PWM
|
53 | TimerInit(); |
54 | |
55 | |
56 | // Timer base configuration
|
57 | // Don't know why, but this code has to be here (not in a seperate method)
|
58 | TIM_TimeBaseStructure.TIM_Period = (uint16_t) (TimerCounterClock / TimerOutputClock); |
59 | TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock /2) / TimerCounterClock) - 1; |
60 | TIM_TimeBaseStructure.TIM_ClockDivision = 0; |
61 | TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; |
62 | |
63 | // basic timer init
|
64 | TIM_TimeBaseInit(MOTORPWMTIMER, &TIM_TimeBaseStructure); |
65 | |
66 | // configure PWM mode and duration
|
67 | TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; |
68 | TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; |
69 | TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here! |
70 | TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; |
71 | TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure); |
72 | TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable); |
73 | |
74 | // preload timer config
|
75 | TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE); |
76 | |
77 | // enable timer / counter
|
78 | TIM_Cmd(MOTORPWMTIMER, ENABLE); |
79 | |
80 | |
81 | //
|
82 | // motor pwm test ! ! !
|
83 | //
|
84 | while(1) |
85 | {
|
86 | for (i=1; i<70; i++) |
87 | {
|
88 | Delay(0x03FFFF); |
89 | TIM_Cmd(MOTORPWMTIMER, DISABLE); |
90 | |
91 | PulseDurationInMicroSeconds = i; |
92 | |
93 | TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; |
94 | TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; |
95 | TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here! |
96 | TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; |
97 | TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure); |
98 | TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable); |
99 | |
100 | TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE); |
101 | |
102 | TIM_Cmd(MOTORPWMTIMER, ENABLE); |
103 | }
|
104 | |
105 | for (i=70; i>2; i--) |
106 | {
|
107 | Delay(0x03FFFF); |
108 | TIM_Cmd(MOTORPWMTIMER, DISABLE); |
109 | |
110 | PulseDurationInMicroSeconds = i; |
111 | |
112 | TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; |
113 | TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; |
114 | TIM_OCInitStructure.TIM_Pulse = PulseDurationInMicroSeconds; // set the duty cycle / pulse here! |
115 | TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; |
116 | TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure); |
117 | TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable); |
118 | |
119 | TIM_ARRPreloadConfig(MOTORPWMTIMER, ENABLE); |
120 | |
121 | TIM_Cmd(MOTORPWMTIMER, ENABLE); |
122 | }
|
123 | }
|
124 | }
|
125 | |
126 | |
127 | /**
|
128 | * @brief Configure the timer for PWM.
|
129 | * @param None
|
130 | * @retval None
|
131 | */
|
132 | void TimerInit(void) |
133 | {
|
134 | // set timer frequencies
|
135 | TimerCounterClock = 1000000; // 1 MHz |
136 | TimerOutputClock = 10000; // 10 kHz = 100 µs period |
137 | |
138 | // set pulse duration in mili seconds (HIGH time)
|
139 | // can be up to from 0 to 99 (due to a TimerOutputClock of 10 kHz)
|
140 | PulseDurationInMicroSeconds = 50; |
141 | |
142 | // Timer clock enable
|
143 | RCC_APB1PeriphClockCmd(MOTORPWMTIMCLOCK, ENABLE); |
144 | |
145 | // Port clock enable
|
146 | RCC_AHB1PeriphClockCmd(MOTORPWMPORTCLOCK, ENABLE); |
147 | |
148 | // Set PWM Port, Pin and method
|
149 | GPIO_InitStructureTimer.GPIO_Pin = MOTORPWMBIT; |
150 | GPIO_InitStructureTimer.GPIO_Mode = GPIO_Mode_AF; |
151 | GPIO_InitStructureTimer.GPIO_Speed = GPIO_Speed_100MHz; |
152 | GPIO_InitStructureTimer.GPIO_OType = GPIO_OType_PP; |
153 | GPIO_InitStructureTimer.GPIO_PuPd = GPIO_PuPd_UP ; |
154 | GPIO_Init(MOTORPWMPORT, &GPIO_InitStructureTimer); |
155 | |
156 | // Connect TIM pin to AF
|
157 | GPIO_PinAFConfig(MOTORPWMPORT, MOTORPWMTIMBIT, MOTORPWMAF); |
158 | }
|
159 | |
160 | |
161 | /**
|
162 | * @brief Delay Function.
|
163 | * @param nCount:specifies the Delay time length.
|
164 | * @retval None
|
165 | */
|
166 | void Delay(__IO uint32_t nCount) |
167 | {
|
168 | while(nCount--) |
169 | {
|
170 | }
|
171 | }
|
Ich hoffe, ich habe nichts vergessen hier rein zu kopieren... Gib mir Bescheid, wenn es nicht läuft. Wie du am englischen Kommentar siehst, funktioniert der Code innerhalb der main Methode komischerweise nicht, wenn ich ihn in eine separate Funktion schiebe. Warum habe ich noch nicht herausgefunden... Das Beispiel aber läuft soweit gut. Das Delay muss natürlich auch nicht sein. Nur der Vollständigkeit halber. Gruß, Markus -- http://www.robotiklabor.de http://www.direcs.de
PS.: Wenn nicht Channel 1 des Timers verwendet wird, müssen die Zeilen
1 | TIM_OC1Init(MOTORPWMTIMER, &TIM_OCInitStructure); |
2 | TIM_OC1PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable); |
natürlich angepasst werden. Für Channel 2 dann z.B.
1 | TIM_OC2Init(MOTORPWMTIMER, &TIM_OCInitStructure); |
2 | TIM_OC2PreloadConfig(MOTORPWMTIMER, TIM_OCPreload_Enable); |
Und so weiter...
small remark regarding while loop markus_k64. it can be as simple as :
1 | |
2 | while ( 1 ) |
3 | {
|
4 | for (i= 1 ; i< 70 ; i++) |
5 | {
|
6 | Delay( 0x03FFFF ); |
7 | |
8 | PulseDurationInMicroSeconds = i; |
9 | |
10 | TIM_SetCompare1(MOTORPWMTIMER, PulseDurationInMicroSeconds); |
11 | }
|
12 | |
13 | for (i= 70 ; i> 2 ; i--) |
14 | {
|
15 | Delay( 0x03FFFF ); |
16 | |
17 | PulseDurationInMicroSeconds = i; |
18 | |
19 | TIM_SetCompare1(MOTORPWMTIMER, PulseDurationInMicroSeconds); |
20 | }
|
21 | }
|
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.
