STM32F4 einfache PWM

Gast #2595209
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
Gast #2595238
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
(Firma: Student) #2595268
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
Gast #2595507
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.
Gast #2595515
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.
(Firma: Student) #2595712
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!
Gast #2595722
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.
Gast #2595775
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);
(Firma: Student) #2595813
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?
Gast #2596379
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren