PWM STM32F405

Gast #3551401
Lesenswert?

Ich habe folgenden Code geschrieben, der mir insgesamt 6 PWM Signale 
liefern soll. Leider tut sich garnichts an den PWM Ausgängen. Was habe 
ich übersehen?
1
void Init_PWM ( void )
2
{
3
  GPIO_InitTypeDef GPIO_InitStructure_A, GPIO_InitStructure_B;
4
  GPIO_StructInit(&GPIO_InitStructure_A);
5
  GPIO_StructInit(&GPIO_InitStructure_B);
6

7
  // IOs als Ausgang initialisieren (PortA und PortB)
8
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
9
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
10

11
  GPIO_InitStructure_A.GPIO_Mode = GPIO_AF_TIM1;
12
  GPIO_InitStructure_A.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;
13
  GPIO_InitStructure_A.GPIO_OType = GPIO_OType_PP;
14
  GPIO_InitStructure_A.GPIO_PuPd =  GPIO_PuPd_DOWN;
15
  GPIO_InitStructure_A.GPIO_Speed = GPIO_Speed_2MHz;
16
  GPIO_Init(GPIOA, &GPIO_InitStructure_A);
17

18
  /////////////////////////////////////////////////////////
19
  GPIO_InitStructure_B.GPIO_Mode = GPIO_AF_TIM1;
20
  GPIO_InitStructure_B.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
21
  GPIO_InitStructure_B.GPIO_OType = GPIO_OType_PP;
22
  GPIO_InitStructure_B.GPIO_PuPd =  GPIO_PuPd_DOWN;
23
  GPIO_InitStructure_B.GPIO_Speed = GPIO_Speed_2MHz;
24
  GPIO_Init(GPIOB, &GPIO_InitStructure_B);
25

26
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM1);
27
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
28
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1);
29
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_TIM1);
30
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1);
31
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM1);
32

33
  /////////////////////////////////////////////////////////
34
  /////////////////////////////////////////////////////////
35
  // Timer
36
  TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
37
  TIM_TimeBaseStructInit(&TIM_TimeBase_InitStructure);
38
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
39

40
  TIM_TimeBase_InitStructure.TIM_Prescaler = 1;
41
  TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
42
  TIM_TimeBase_InitStructure.TIM_Period = 32000;
43
  TIM_TimeBase_InitStructure.TIM_ClockDivision = 0;
44
  TIM_TimeBase_InitStructure.TIM_RepetitionCounter = 0;
45

46
  TIM_TimeBaseInit(TIM1, &TIM_TimeBase_InitStructure);
47
  TIM_UpdateRequestConfig(TIM1, TIM_UpdateSource_Global);
48
  TIM_UpdateDisableConfig(TIM1,DISABLE);
49

50
  /////////////////////////////////////////////////////////
51
  /////////////////////////////////////////////////////////
52
  // PWM
53
  TIM_OCInitTypeDef TIM_OCInitStructure;
54
  TIM_OCStructInit(&TIM_OCInitStructure);
55
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
56
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
57
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
58
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
59
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
60
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
61
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
62

63
  TIM_OCInitStructure.TIM_Pulse = 16000;
64
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
65
  TIM_OCInitStructure.TIM_Pulse = 16000;
66
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
67
  TIM_OCInitStructure.TIM_Pulse = 16000;
68
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);
69

70
  /////////////////////////////////////////////////////////
71
  /////////////////////////////////////////////////////////
72
  // Dead-Time
73
  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
74
  TIM_BDTRStructInit(&TIM_BDTRInitStructure);
75
  /* Automatic Output enable, Break, dead time and lock configuration*/
76
  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
77
  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
78
  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
79
  TIM_BDTRInitStructure.TIM_DeadTime = 100;
80
  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
81
  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
82
  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
83
  TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
84

85
  /* Enable Timer */
86
  TIM_Cmd( TIM1, ENABLE );
87
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
88

89
  // Set Duty
90
  TIM_SetCompare1(TIM1,16000);
91
  TIM_SetCompare2(TIM1,16000);
92
  TIM_SetCompare3(TIM1,16000);
93

94

95
}

Kann mir jemand helfen? Die Funktion soll die PWM initialisieren und den 
Tastgrad auf 50% setzen, aber nichts passiert, es gibt auch keine 
Compilerwarnungen... Der Rest der CPU funktioniert einwandfrei. Ich 
könnte wetten ich hab irgend einen "Schalter" übersehen...


Ingo
Gast #3552008
Lesenswert?

Ich hab hier mal ein PWM-Example. So wie ich es sehe fehlen bei dir die 
PreloadConfigs (siehe unten im Code)

Gruß
1
void TIMER_PWM_INIT_EXAMPLE(void)
2
{
3

4

5
    // TIM4 clock enable
6
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
7

8
    // GPIOD Clock enable
9
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
10

11
    // GPIO Config
12
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;
13
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
14
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
15
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
16
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
17
    GPIO_Init(GPIOD, &GPIO_InitStructure);
18
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4); // Verbindet den Pin12 über die Multiplexerfunktion mit AF2/TIM4
19
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4); // Verbindet den Pin13 über die Multiplexerfunktion mit AF2/TIM4
20

21
    // Timer Config
22
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
23
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
24
    TIM_TimeBaseInitStructure.TIM_Period = 0x3FF-1; // 10bit Auflösung der PWM
25
    TIM_TimeBaseInitStructure.TIM_Prescaler = 100-1; // 84MHz / 100 = 0,84 MHz nach dem Prescaler
26
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
27
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
28

29
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
30
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
31
    TIM_OCInitStructure.TIM_Pulse = 0;
32
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
33
    TIM_OC1Init(TIM4, &TIM_OCInitStructure);
34
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);
35

36
    TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
37
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
38

39
    TIM_ARRPreloadConfig(TIM4, ENABLE);
40
    TIM_Cmd(TIM4, ENABLE);
41

42
    TIM4->CCR1 = 0;
43
    TIM4->CCR2 = 0;
44
}
Gast #3552010
Lesenswert?

Ingo schrieb:
> GPIO_InitStructure_B.GPIO_Mode = GPIO_AF_TIM1;
Das ist verkehrt, da muss GPIO_Mode_AF hin

Ingo schrieb:
> GPIO_InitStructure_A.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 |
> GPIO_Pin_10 ;
> GPIO_InitStructure_B.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
Sicher dass man die 4 Kanäle des Timers auf diese 6 Pins ausgeben kann? 
Überprüft in der AF tabelle im Datasheet?
Gast #3552023
Lesenswert?

Dr. Sommer schrieb:
> Helfer schrieb:
>>     TIM4->CCR1 = 0;
> Wieso schaltest du den Timer und Preload direkt wieder aus?

Sorry - habs aus dem Zusammenhang eines alten Projektes gerissen und 
gepostet. Im Code wird an anderer Stelle das CCR1 Register gesetzt. Es 
sollte bei der Initialisierung erstmal auf 0 stehen.
Gast #3552174
Lesenswert?

Helfer schrieb:
> Den Timer schalte ich da nicht aus - ich setze nur das Capture Compare
> Register auf 0.
Upps, Knick in der Optik, ich hatte "CR" gelesen.

Ingo schrieb:
> Ich werde es morgen mal ausprobieren. Ja die 3 Kanäle kann auf diesen
> Pins ausgeben (AF1).
Sicher dass die auch auf 6 Pins gleichzeitig ausgegeben werden 
können?!
Gast #3552203
Lesenswert?

Ingo schrieb:
> Ich bin nicht am PC, kann es erst morgen testen. Aber der Fehler
> mit dem
> AF war dämlich. Was genau machen die Preload Register? Ich bin mit'm
> Handy im www..

steht alles im Besipiel. Kannst es doch einfach auf deine Anwendung 
übertragen...


Datenblatt sagt dazu:
The PWM mode can be selected independently on each channel (one PWM per 
OCx
output) by writing ‘110’ (PWM mode 1) or ‘111’ (PWM mode 2) in the OCxM 
bits in the
TIMx_CCMRx register. You must enable the corresponding preload register 
by setting the
OCxPE bit in the TIMx_CCMRx register, and eventually the auto-reload 
preload register (in
upcounting or center-aligned modes) by setting the ARPE bit in the 
TIMx_CR1 register.
Gast #3552206
Lesenswert?

Ingo schrieb:
> Was genau machen die Preload Register?
Wenn eingeschaltet, wird der neue Max.-Zähler-Wert (TIM_Period = 32000) 
nicht sofort, sondern erst bei einem Update Event (= wenn der Timer 
oben/unten ankommt) angewendet.

Ingo schrieb:
> Ich habe doch 3 Kanäle des Timers in Betrieb. Oder was meinst du?
> Worauf
> willst du hinaus? Vielleicht tappe ich in eine Fälle die ich noch
> garnicht sehe
Achja, die positiven und negativen Ausgaben, die hatte ich vergessen.
Gast #3552221
Lesenswert?

Ok, wo wir schonmal dabei sind, ich hoffe es ist ok wenn ich frage. Wann 
updated der Controller den compare wert?

Am besten wäre wenn er den Wert aus dem Register immer bei Bottom 
aktualisiert, so verhindert man überlange Pulse. Kann der Controller 
das?

Was hat es mit dem Pulse Register auf sich? Worin besteht der 
Unterschied zwischen dem Compareregister?
Gast #3553077
Lesenswert?

So, läuft... Es lag an dem falschen
1
GPIO_InitStructure_B.GPIO_Mode = GPIO_AF_TIM1;
und an dem fehlenden
1
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
für die jeweiligen Kanäle...

Könnte mir mal jemand die Dead-Time Berechnung erklären? Was im 
Datenblatt steht verstehe ich nicht wirklich:
*********************
Bits 7:0 DTG[7:0]: Dead-time generator setup
This bit-field defines the duration of the dead-time inserted between 
the complementary
outputs. DT correspond to this duration.
DTG[7:5]=0xx => DT=DTG[7:0]x tdtg with tdtg=tDTS.
DTG[7:5]=10x => DT=(64+DTG[5:0])xtdtg with Tdtg=2xtDTS.
DTG[7:5]=110 => DT=(32+DTG[4:0])xtdtg with Tdtg=8xtDTS.
DTG[7:5]=111 => DT=(32+DTG[4:0])xtdtg with Tdtg=16xtDTS.
Example if TDTS=125ns (8MHz), dead-time possible values are:
0 to 15875 ns by 125 ns steps,
16 us to 31750 ns by 250 ns steps,
32 us to 63us by 1 us steps,
64 us to 126 us by 2 us steps
Note: This bit-field can not be modified as long as LOCK level 1, 2 or 3 
has been programmed
(LOCK bits in TIMx_BDTR register).
*********************

Hab mir die Deadtime jetzt so hinprobiert wie ich sie brauche, aber wie 
der Wert zu stande kommt kann ich nur Mutmaßen.
1
TIM_BDTRInitStructure.TIM_DeadTime = 223;
gibt bei mir 3us Totzeit. Systemtakt ist 168MHz.
#3554906
Lesenswert?

Ingo schrieb:
> Also ich komme rechnerisch nicht auf diesen Wert. Kann mir mal jemand
> auf die Sprünge helfen?

1. Dein Timer1 läuft mit 168MHz (CK_INT = 168MHz)
2. Vorteiler ist auf 1 -> damit ist (TDTS = 168MHz)
3. Du setzt "DTG" auf 223dez = 0xDF
4. 0xDF = "1101.1111" Binär

Also ist DTG[7:0] = "1101.1111"

Rechnung :

DTG Bit[7:5] legen den Mode fest "110" ->
DT=(32+DTG[4:0])xtdtg with Tdtg=8xtDTS

DTG Bit[4:0] legt den Wert fest "11111" = 31

DT=(32+31) x 8 x 1/168MHz = 3us

sollte so stimmen

Gruss Uwe

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