Forum: Mikrocontroller und Digitale Elektronik PWM STM32F405


von Ingo (Gast)


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

von Ingo (Gast)


Lesenswert?

Push

von Ingo (Gast)


Lesenswert?

Keiner ne Idee?

von Helfer (Gast)


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
}

von Dr. Sommer (Gast)


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?

von Dr. Sommer (Gast)


Lesenswert?

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

von Ingo (Gast)


Lesenswert?

@ Dr. Sommer
Ich werde es morgen mal ausprobieren. Ja die 3 Kanäle kann auf diesen 
Pins ausgeben (AF1).

von Helfer (Gast)


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.

von Helfer (Gast)


Lesenswert?

Ergänzung:

Den Timer schalte ich da nicht aus - ich setze nur das Capture Compare 
Register auf 0.

von Dr. Sommer (Gast)


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?!

von Ingo (Gast)


Lesenswert?

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

von Helfer (Gast)


Lesenswert?

@ Ingo,

was ist denn jetzt mit dem Preload Register? Das hast du nicht 
enabled...

von Ingo (Gast)


Lesenswert?

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..

von Helfer (Gast)


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.

von Dr. Sommer (Gast)


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.

von Ingo (Gast)


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?

von Ingo (Gast)


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.

von Ingo (Gast)


Lesenswert?

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

von Uwe B. (derexponent)


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

: Bearbeitet durch User
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.