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 ;)