Forum: Mikrocontroller und Digitale Elektronik STM32F4 einfache PWM


von Pief (Gast)


Lesenswert?

Ich will nicht lang drumrum reden: PWM soll eine der 4 Onboard LEDs hoch 
und runter-drimmen und das funktioniert nicht. Hier der gesamte Code:
1
/* Includes */
2
#include "stm32f4xx.h"
3
4
/* Private macro */
5
/* Private variables */
6
/* Private function prototypes */
7
/* Private functions */
8
9
10
void delay()
11
{
12
  volatile uint32_t delayCount = 262143;
13
14
  while(delayCount > 0)
15
    delayCount--;
16
}
17
18
void initPWM_LED(void)
19
{
20
  TIM_OCInitTypeDef  TIM_OCInitStructure;
21
  GPIO_InitTypeDef  GPIO_InitStructureTimerPin;
22
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
23
24
25
  //timer and port clock enable
26
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
27
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
28
29
  //general port settings
30
  GPIO_InitStructureTimerPin.GPIO_Mode = GPIO_Mode_AF;
31
  GPIO_InitStructureTimerPin.GPIO_Speed = GPIO_Speed_100MHz;
32
  GPIO_InitStructureTimerPin.GPIO_OType = GPIO_OType_PP;
33
  GPIO_InitStructureTimerPin.GPIO_PuPd = GPIO_PuPd_UP ;
34
35
  //set pin 12 to output
36
  GPIO_InitStructureTimerPin.GPIO_Pin = GPIO_Pin_12;
37
  GPIO_Init(GPIOD, &GPIO_InitStructureTimerPin);
38
39
  //set pin 13 to output
40
  GPIO_InitStructureTimerPin.GPIO_Pin = GPIO_Pin_13;
41
  GPIO_Init(GPIOD, &GPIO_InitStructureTimerPin);
42
43
  //set pin 14 to output
44
  GPIO_InitStructureTimerPin.GPIO_Pin = GPIO_Pin_14;
45
  GPIO_Init(GPIOD, &GPIO_InitStructureTimerPin);
46
47
  //set pin 15 to output
48
  GPIO_InitStructureTimerPin.GPIO_Pin = GPIO_Pin_15;
49
  GPIO_Init(GPIOD, &GPIO_InitStructureTimerPin);
50
51
  //connect TIM4 CH1..5 to PD12..15
52
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
53
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
54
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4);
55
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4);
56
57
  //timer frequency 1kHz
58
  uint32_t timer_clk=1000000;
59
  uint32_t timer_out_clk=1000;
60
61
  //timer base configuration
62
  TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/timer_clk)-1);
63
  TIM_TimeBaseStructure.TIM_Period = (timer_clk/timer_out_clk);
64
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
65
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
66
67
  //timer init
68
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
69
70
  //common PWM config
71
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
72
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
73
74
  //special PWM config CH1
75
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
76
  TIM_OCInitStructure.TIM_Pulse = (timer_clk/timer_out_clk)/1;
77
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);
78
  TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
79
80
  //special PWM config CH2
81
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
82
  TIM_OCInitStructure.TIM_Pulse = (timer_clk/timer_out_clk)/1;
83
  TIM_OC2Init(TIM4, &TIM_OCInitStructure);
84
  TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
85
86
  //special PWM config CH3
87
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
88
  TIM_OCInitStructure.TIM_Pulse = (timer_clk/timer_out_clk)/1;
89
  TIM_OC3Init(TIM4, &TIM_OCInitStructure);
90
  TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
91
92
  //special PWM config CH4
93
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
94
  TIM_OCInitStructure.TIM_Pulse = (timer_clk/timer_out_clk)/1;
95
  TIM_OC4Init(TIM4, &TIM_OCInitStructure);
96
  TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
97
98
  // preload timer config
99
  TIM_ARRPreloadConfig(TIM4, ENABLE);
100
101
  // enable timer / counter
102
  TIM_Cmd(TIM4, ENABLE);
103
}
104
105
int main(void)
106
{
107
  initPWM_LED();
108
  TIM_OCInitTypeDef TIM_OCInitStructure;
109
  int i;
110
111
  //while(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))
112
  //{;}
113
114
  while(1)
115
  {
116
    for(i=0;i<1000;i++)
117
    {
118
          TIM_Cmd(TIM4, DISABLE);
119
120
          TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
121
          TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
122
          TIM_OCInitStructure.TIM_Pulse = i;
123
          TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
124
          TIM_OC4Init(TIM4, &TIM_OCInitStructure);
125
          TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
126
127
          TIM_ARRPreloadConfig(TIM4, ENABLE);
128
          delay();
129
    }
130
  }
131
}


Ich finde den Fehler nicht, vlt. bin ich betriebsblind vom vielen 
rumprobieren.

Danke

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Hier
Beitrag "Re: STM32 Servoansteuerung PWM"
hab ich nen Code gepostet zum steuern von Servos über den STM32F4, was 
ja auch per PWM passiert. Damit kann man dann auch LED's dimmen, das 
ggf. noch durch Änderung der Parameter optimieren (Prescaler, Period, 
Pulse)

von Pief (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Hier
> Beitrag "Re: STM32 Servoansteuerung PWM"
> hab ich nen Code gepostet zum steuern von Servos über den STM32F4, was
> ja auch per PWM passiert. Damit kann man dann auch LED's dimmen, das
> ggf. noch durch Änderung der Parameter optimieren (Prescaler, Period,
> Pulse)

Und durch vergleich sehe ich keinen Unterschied?!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Dann beschreibe doch mal was da nicht geht...

von Flo (Gast)


Lesenswert?

Pief schrieb:
> for(i=0;i<1000;i++)
>     {
>           TIM_Cmd(TIM4, DISABLE);
>
>           TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
>           TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
>           TIM_OCInitStructure.TIM_Pulse = i;
>           TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
>           TIM_OC4Init(TIM4, &TIM_OCInitStructure);
>           TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
>
>           TIM_ARRPreloadConfig(TIM4, ENABLE);
>           delay();
>     }

das ist nicht ganz der richtige weg,
bin jetzt nicht gerade im saft,
aber du reinitialiserst ständig diesen pwm

das ist eine timing sache.
soll: im prinziep gibst du dem timer im laufenden betrieb
den neuen wert, ohne die die anderen register neu zu bespielen

abgesehen davon ist das jede menge code für eine pwm steuerung

gib mir mal ne sekunde,
such eben mal den zugriff raus

von Florian G. (Firma: Student) (flogo)


Lesenswert?

lass die initialisierung in deiner schleife weg und schreibe stattdessen
1
TIM4->CCR1 = Deine_Variable;
2
TIM4->CCR2 = Deine_Variable;
3
.
4
.
5
.

ich weiß auch garnicht ob das so sinnvoll ist,
dass was du machst!

deine pwm braucht mehrere zyklen,
und wenn ich das richtig sehe,
würgst du den schon mitten drin ab

mit dem direktzugriff,
wird die pwm einmal durchgeführt,
und dann wird der nächste wert übernommen,
aber wenn der spaß mehrere zyklen dauert,
und du mit jeden zyklus mit +1 inkrementierst,
kann es sein das dieser eine wesentlich höhere zahl übernimmt

von Pief (Gast)


Lesenswert?

Danke für die antworten, aber sorry leute: ICh versteh nur bahnhof

Das mit jedem jedes mal neu initialisieren erscheint mir als einziger 
Weg überhaupt ansatzweise zu funktionieren. Wenn ich nur den 
Pulsbreitenwert einmal beschreibe (ohne for-schleife) tut sich gor nix.

Ich muss mindestens den TIM abschalten und wieder abschalten.

@Flo: Wieso würge ich die PWM ab? Ich hab doch ein fettes delay 
eingebaut.

von Pief (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Hier
> Beitrag "Re: STM32 Servoansteuerung PWM"
> hab ich nen Code gepostet zum steuern von Servos über den STM32F4, was
> ja auch per PWM passiert. Damit kann man dann auch LED's dimmen, das
> ggf. noch durch Änderung der Parameter optimieren (Prescaler, Period,
> Pulse)

Sorry, ich hab zu vorschnell abgewiesen. Ich guck mir deinen Code 
nochmal genauer an und studiere ihn. Danke dafür.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Pief schrieb:
> @Flo: Wieso würge ich die PWM ab? Ich hab doch ein fettes delay
> eingebaut.
Bei den 168 MHz die so ein STM32F4 hat ist das delay jetzt gar nicht mal 
sooo lang. Je nachdem wie der Timer eingestellt ist...

von Florian G. (Firma: Student) (flogo)


Lesenswert?

das delay selbst hab ich jetzt übersehen,

tut aber nichts zur sache...
stimmt die länge des delay nicht,
haste da ein problem

schau dir mal die pheripherie datasheet mal an,
da steht auch die funktionsweise der register

da siehste dass das hw pwm für sich selbst arbeitet,
da musste selbst nicht manuell neu starten,
und übergibst nur den neuen wert (pulsbreite)
den er beim nächsten zählen übernimmt...

du mischt gerade soft und hardware pwm!!!

deswegen einmal kurz nachlesen!

von Pief (Gast)


Lesenswert?

Was ich eigentlich möchte ist die LED dunkel nach hell zu fahren. Das 
ist der SInn der For-Schleife. Ich dachte das geht aus dem Code hervor, 
hat aber jetzt keiner so verstanden, oder?

Ich möchte einfach das Duty Cycle von 0% nach 100% laufen lassen.

von Pief (Gast)


Lesenswert?

Ich habe die Main jetzt folgendermaßen abgeändert. so funktioniert es:

1
int main(void)
2
{
3
  initPWM_LED();
4
  initButtons();
5
6
  uint16_t i;
7
8
  while(1)
9
  {
10
    for (i = 0; i < 300; i++)
11
    {
12
      TIM_SetCompare1(TIM4,i);
13
      TIM_SetCompare2(TIM4,i);
14
      TIM_SetCompare3(TIM4,i);
15
      TIM_SetCompare4(TIM4,i);
16
      delay();
17
    }
18
    for (i = 300; i > 0; i--)
19
    {
20
      TIM_SetCompare1(TIM4,i);
21
      TIM_SetCompare2(TIM4,i);
22
      TIM_SetCompare3(TIM4,i);
23
      TIM_SetCompare4(TIM4,i);
24
      delay();
25
    }
26
  }
27
}


Wo liegt denn jetzt der unterschied zwischen:

1
TIM_SetCompare3(TIM4,i);

und
1
TIM_Cmd(TIM4, DISABLE);
2
TIM_OCInitStructure.TIM_Pulse = i;
3
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
4
TIM_Cmd(TIM4, ENABLE);

von Florian G. (Firma: Student) (flogo)


Lesenswert?

während setcompare (den befehl so kannte ich noch garnicht),
quasi das macht, was ich schon vorhin versucht habe dir zu erklären,
also den wert in das entsprechende register reinschreibt,
und der mc selbsständig darauf zurückgreift, ohne(!) den timer zu 
stoppen

deine intialisierung in der schleife hat zur folge, dass
bei jedem zugriff (!) der timer gestoppt (!)
der wert neu gesetzt wird, und der timer neu gestartet wird,
mit anderen worten, der kommt garnicht zum zählen,
da dieser wieder gestoppt wird um neu beschrieben zu werden

verstehste was ich meine?

von Florian G. (Firma: Student) (flogo)


Lesenswert?

btw. statt dem delay kannste auch ein timerinterrupt auslösen lassen,
der den wert um einen erhöhen lässt,
und ins register schreiben lässt.

die main while schleife kann frei bleiben

von Pief (Gast)


Lesenswert?

Florian G. schrieb:
> verstehste was ich meine?

Jau danke.


Florian G. schrieb:
> die main while schleife kann frei bleiben

Jau verstehe ich auch, wollts ja nur testen. Irgendwo hier im Forum hab 
ich mir ne funktionierende PWM abgeschaut die das leider genauso macht 
mit dem deinitialisieren, beschreiben, neuinitialisieren. Jeztt hab ich 
wieder was dazu gelernt.

von Florian G. (Firma: Student) (flogo)


Lesenswert?

moin kein ding,
vor 3 monaten stand ich genau vor dem selben problem,
deswegen wusste ich auch auf anhieb wo das problem lag ^^

sag mir mal eben mit welcher standart pheripherie library du arbeitest?

von Pief (Gast)


Lesenswert?

StdPeriph_Lib_V1.0.0 / 30-September-2011

Content:
    Cortex-M CMSIS V2.1 (release notes)
    CMSIS DSP Software Library V1.0.10  (release notes)
    STM32F4xx CMSIS V1.0.0 (release notes)
    STM32F4xx_StdPeriph_Driver V1.0.0 (release notes)
    STM32F34xx_StdPeriph_Examples V1.0.0 (release notes)
    STM32F4xx_StdPeriph_Templates V1.0.0 (release notes)
    STM32_EVAL Common drivers V5.0.0 (release notes)
    STM3240_41_G_EVAL board drivers V1.0.0 (release notes)

von Pief (Gast)


Lesenswert?

Könnte mir noch jemand erklären, was ich konfigurieren muss um einen 
Interrupt mit Frequenz x auslösen zu lassen?

von Flo (Gast)


Lesenswert?

da ich gerade auf den sprung bin,
schau dir das nvic register an,
da gibs du an welcher interrupt ausgelöst werden soll,
bei welcher "source"...
aber was meinst du genau mit "frequenz"?

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

hier mal die initialiesierung und Infos zum Takt von Timer2.

1/Frequenz ist deine Taktrate.


Gruß xmega

von Moritz M. (avrprogger)


Angehängte Dateien:

Lesenswert?

Hallo hier mal ein beispiel

Moritz

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
Noch kein Account? Hier anmelden.