Forum: Mikrocontroller und Digitale Elektronik STM32 Timer-Periode einstellen


von Lars (Gast)


Lesenswert?

Hi,

kann mir jmd kurz erklären, wie ich den Timer Interrupt beim STM32F103 
einstellen muss, damit dieser 120x pro Sekunde ausschlägt (also alle 
8.333 ms)? Der Prozessor läuft mit 72MHz, wobei die PCLK1 = HCLK/2 ist.
1
    /* init timer2 update interrupt */
2
    TIM_TimeBaseStructure.TIM_Period = freq; //120 interrupts pro sekunde 
3
    TIM_TimeBaseStructure.TIM_Prescaler = (36000 - 1);
4
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;   
5
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
6
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;


Gruß
Lars

von Steffen (Gast)


Lesenswert?

SYSCLK    = 36000000
prescaler = 100
frequenz  = 120

SYSCLK  prescaler  frequenz  = 3000;

TIM_TimeBaseStructure.TIM_Period = 3000;
TIM_TimeBaseStructure.TIM_Prescaler = prescaler -1;

von Steffen (Gast)


Lesenswert?

SYSCLK (div) prescaler (div) frequenz  = 3000;

von Lars (Gast)


Lesenswert?

Steffen schrieb:
> TIM_TimeBaseStructure.TIM_Period = 3000;
> TIM_TimeBaseStructure.TIM_Prescaler = prescaler -1;

Und wie sieht das aus, wenn der Interrupt 119,88x pro Sekunde 
ausschlagen soll? Kann man das überhaupt in dieser Genauigkeit 
realisieren? Hintergrund ist, ich möchte gern einen Midi Timecode 
generieren und bei 30fps mit Dropframe müssen die Pakete alle 199.88x 
pro Sekunde versendet werden.

von Reinhard B. (brainstorm)


Lesenswert?

Lars schrieb:
> Und wie sieht das aus, wenn der Interrupt 119,88x pro Sekunde
> ausschlagen soll?

Und in Zukunft fragst du jedesmal, wenn du einen Timer brauchst hier im 
Forum nach oder wie? :-)

- Der Timer-"Baustein" im Controller wird mit einem bestimmten Takt 
versorgt. Wie du schon richtig angibst ist das der PCLK1 (oder auch 
PCLK2 bei anderen Timern, siehe Datasheet).
- Dieser Takt wird jetzt erstmal vom Prescaler heruntergeteilt. Also 
Timertakt = PCLKx / Prescaler.
- Der Timer selbst zählt nun mit diesem Takt sein CNT Register hoch oder 
runter. Wie lange er dafür brauchen soll gibst du ja vor - du musst ihm 
also sagen, von wo an er wegzählen soll.

Du verlangst 199,88x pro Sekunde, also alle 5,003ms. Deine PCLK hat eine 
Periode von 1/36MHz = 27,778ns. Ohne Prescaler müsste dein Timer also 
5,003ms/27,778ns = 180108 mal zählen. Da das größer ist, als der 
höchstmögliche Wert im CNT Register (16bit -> 65535), musst du den Takt 
mit dem Prescaler runterteilen, z. B. durch 3. Dann ergibt sich der 
Zähler Takt zu 36MHz/3 = 12MHz, was einer Periode von 83,33ns 
entspricht. Damit muss dein Timer jetzt 5,003ms/83,33ns = 60036 mal 
zählen.

Die Genauigkeit lässt sich halt auf +/- einen Timer-Zählschritt 
einstellen. Ich denke mal bei 36MHz Grundtakt und 200Hz Timerfrequenz 
solltest du dir darüber keine Sorgen machen müssen.

mfg

von Lars (Gast)


Lesenswert?

Reinhard B. schrieb:
> Und in Zukunft fragst du jedesmal, wenn du einen Timer brauchst hier im
> Forum nach oder wie? :-)

Nein, ich versuch das ganze schon zu verstehen. Bis jetzt hats aber 
leider noch nicht klick gemacht.

PCLK1 = 36MHz
Prescaler 1000
-> Timerfrequenz = PCLK1 / Prescaler = 36000
Periode = 300
-> Timer-Interrupt 8.33ms

Bei diesen Angaben toggelt meine LED mit 40Hz. Irgendwas übersehe ich im 
Datenblatt allerdings noch.

Was auch sehr komisch ist; egal welchen Wert ich für den Prescaler 
angebe (1000, 2000 oder 4000), das Timerintervall bleibt bei 40Hz.

Setze ich die Periode von 300 auf 200 dann erhalte ich 60Hz. Bei einer 
Periode von 100 erhalte ich dann die 120Hz.
1
    TIM_TimeBaseStructure.TIM_Period = 100-1; 
2
    TIM_TimeBaseStructure.TIM_Prescaler = 1000 - 1;   
3
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;   
4
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
5
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);

Gruß
Lars

von Reinhard B. (brainstorm)


Lesenswert?

Lars schrieb:
> Was auch sehr komisch ist; egal welchen Wert ich für den Prescaler
> angebe (1000, 2000 oder 4000), das Timerintervall bleibt bei 40Hz.

Kann nicht sein, da stimmt was nicht. Außer du berechnest die Periode 
aus Peripherie-Takt, Prescaler und einer vorgegebenen Zeit, dann muss 
das Intervall natürlich gleich lang bleiben.

Zeig doch mal den kompletten Code her.

von Lars (Gast)


Lesenswert?

hab meinen Fehler gerade gefunden. Hatte vergessen den Prescaler-Value 
in der TIM_PrescalerConfig() Funktion entsprechend anzupassen.

Gruß
Lars

von Daniel (Gast)


Lesenswert?

f_timer= (SystemCoreClock / (1+Prescaler))/ Period

von Yoldas (Gast)


Lesenswert?

Hallo Leute wollte keinen neuen Thread erstellen ich habe auch ein 
Problem mit dem Timer...folgendes:

Ich habe einen STM32F100... möchte mit dem UserButton den Timer 
einschalten und mit dem nächsten Tastendruck wieder ausschalten.

bei 24Mhz habe ich den Prescaler mit 23999 gewählt somit habe ich eine 
Frequenz von 1kHz bzw 1ms Umlaufzeit. Die Periode habe ich mit 19999 
gewählt somit könnte ich bis zu 20ms erfassen.

Wenn ich den Cnt wert des Timers auslese stimmt das nicht im geringsten 
überein.

Für 10s kommen im Cnt 3100ms raus also 3,1s.

Ein Freund hat eine neuere Version von Keil bei ihm funktioniert es 
richtig kann es an dem liegen?

von X2 (Gast)


Lesenswert?

Läuft das Programm während du über einen Debugger damit verbunden bist? 
Wenn ja, mal ohne Debugger probieren.

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.