Forum: Mikrocontroller und Digitale Elektronik Frage zu Timern/PWM beim STM32


von Chris (Gast)


Lesenswert?

Hallo,

ich arbeite mich gerade auf einem SMT32L151 ein und versuche mich schon 
seit einem Tag an dessen Timer, komm aber nicht ganz dahinter wie ich 
die Taktrate für Timer berechne, welche ich für ein PWM Signal und 
interen Interrupts verwenden will. Der STM32 hat einen externen 8 MHz 
Quarz für die Taktgenerierung, zum Programieren verwende ich Atollic 
TrueStudio.

Meine system_stm32l1xx.c hab ich mir durch die Datei 
STM32L1xx_Clock_Configuration_V1.2.0.xls von ST erstellen lassen, die 
Einstellungen sind wie folgt:
1
System Clock Configuration
2
System Clock source          | PLL(HSE)
3
SYSCLK                       | 8000000 Hz
4
HCLK                         | 2000000 Hz
5
AHB Prescaler                | 4
6
APB1 Prescaler               | 1
7
APB2 Prescaler               | 1
8
HSE Frequency                | 8000000 Hz
9
PLL DIV                      | 3
10
PLL MUL                      | 3
11
VDD                          | 3.3 V
12
Vcore                        | 1.5 V (Range 2)
13
Flash Latency                | 0 WS
14
Require 48MHz for USB clock  | Disabled

Mein "Problem" liegt warscheinlich in meiner InitPWM Funktion:
1
void InitPWM()
2
{
3
  // Clock anschalten; APB1 = SYSCLK / AHB Prescaler = 8 MHz / 4 = 2 MHz
4
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
5
6
  TIM_TimeBaseInitTypeDef TimerInitStructure;
7
  TimerInitStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned3;
8
  
9
  // keine Teilung => 2 MHz
10
  TimerInitStructure.TIM_Prescaler = 1 -1;        
11
  
12
  // keine Teilung => 2 MHz
13
  TimerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // TIM_CKD_DIV1 = ( (uint16_t)0x0000 )
14
15
  // 2 MHz / 100 = 20 kHz => T = 50 µs
16
  TimerInitStructure.TIM_Period = 100 -1;
17
18
  TIM_TimeBaseInit(TIM2, &TimerInitStructure);
19
  TIM_Cmd(TIM2, ENABLE);
20
21
  // init PWM Channel
22
  TIM_OCInitTypeDef PWM_OutputChannelInit;
23
24
  // PWM1 erzeugt nicht-invertiertes Signal, PWM2 invertiertes Signal
25
  PWM_OutputChannelInit.TIM_OCMode = TIM_OCMode_PWM1;
26
  PWM_OutputChannelInit.TIM_Pulse = 10;
27
  PWM_OutputChannelInit.TIM_OutputState = TIM_OutputState_Enable;
28
  PWM_OutputChannelInit.TIM_OCPolarity = TIM_OCPolarity_High;
29
30
  TIM_OC1Init(TIM2, &PWM_OutputChannelInit);
31
  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
32
33
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);
34
35
  // kurze Peaks erzeugen
36
  TIM2->CCR1 = 1;
37
}

Der Code funktioniert, am Oszi sehe ich auch die kurzen Peaks, 
allerdings mit halber Frequenz. Die Zeit zwischen den Pulsen ist also 
100µs => 10 kHz. Wo habe ich den Fehler in meiner Berechnung? Setzt ich 
den Prescaler auf 2-1 verdoppelt sich die Periodenzeit am Oszi auf 
200µs, soweit also ok.

Außerdem ist mir nicht ganz klar warum das ändern der TIM_ClockDivision 
auf z.B. TIM_CKD_DIV2 = ( (uint16_t)0x0100 ) keine Auswirkung hat. Liegt 
das daran, dass der APB1 Prescaler = 1 ist und daher die ClockDivision 
generell ignoriert wird?

Ich habe nun schon einiges gelesen aber komme nicht dahinter wie diese 
Berechnung auszusehen hat. Bislang habe ich nur ein wenig mit Atmegas zu 
tun gehabt, daher fällt mir das verstehen der vielen Timer beim STM32 
gleich doppelt schwer ;)

von Chris (Gast)


Lesenswert?

Ich bin mitlerweile selbst auf die Lösung gekommen, zumindestens 
teilweise.

Die TIM_CKD_DIVx Divider haben scheinbar nur Einfluss, wenn ein interner 
Takt verwendet wird.

Warum die Periodenzeit aber nicht stimmt weiß ich nicht, ich könnte mir 
nur erklären dass es am TIM_CounterMode_CenterAligned3 liegt welcher 
rauf und runter zählt.

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.