Forum: Mikrocontroller und Digitale Elektronik STM32 Timer will nicht so wie ich es will


von Thomas B. (escamoteur)


Lesenswert?

Hi,

ich möchte gerne einen einfachen Timer nutzen.

Aus den Beispielen habe ich mir das hier rausgesucht:
1
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
2
3
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
4
    /* Time base configuration */
5
  TIM_TimeBaseStructure.TIM_Period = 65535;
6
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
7
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
8
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
9
10
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
11
12
  NVIC_InitTypeDef NVIC_InitStructure;
13
 /* Enable the Interrupt */
14
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
15
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
16
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
17
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
18
  NVIC_Init(&NVIC_InitStructure);
19
20
 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
21
22
 TIM_Cmd(TIM2, ENABLE);

Mein Interrupt wird auch angesprungen, aber egal was ich für Werte für 
Period oder Prescaler setze, das Interval ist immer 6,4µs. Den Wert habe 
ich vom Logiganalyser, da ich im Interrupt Handler einen Pin toggle.

Hat einer von euch ne Idee?  Eigentlich will ich einfach einen Timer 
initialisieren, der mir nach definierter Zeit einen IRQ auslöst, es sei 
denn ich setze den Timer davor auf Null zurück.
Kann doch eigentlich nicht so kompliziert sein. Die ganzen Beispiele 
betreffen alle gleich viel komplizierte Anwendungen.

Gruß
Tom

von (prx) A. K. (prx)


Lesenswert?

Eine subtile Kleinigkeit über die ich anfangs gestolpert war: Die 
prescaler und auto-reload Werte der Timer werden nicht sofort wirksam, 
sondern erst beim update event landen sie wirklich da wo sie sich 
nützlich machen. Da kann es sein, dass man nach Programmierung der Werte 
dieses Event manuell auslösen muss (reg EGR bit UG), weil sie sonst nie 
wirksam werden.

Wie sich das in der FWlib darstellt weiss ich nicht.

von Matthias K. (matthiask)


Lesenswert?

Du solltest den TIM-Prescalar höher setzen, hier ein Bsp. für 10ms bei 
72Mhz:
1
//***********************************************************************************************
2
// Timer-Einstellungen
3
//***********************************************************************************************
4
void SetupTimer (void) {
5
#define TIMER_TAKT 10000                                            /* Timer wird mit 10kHz getaktet */
6
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
7
  uint16_t PrescalerValue;
8
9
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);              // TIMER 2 Takt freigeben
10
11
  PrescalerValue = (uint16_t) (SystemCoreClock / TIMER_TAKT) - 1;   // Vorteiler berechnen
12
13
  // Timer Grundkonfiguration
14
  TIM_TimeBaseStructure.TIM_Period = 100;                         // Timer zählt von 0 ... 100
15
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
16
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
17
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
18
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);                   // Timer einstellen
19
20
  //Timer Vorteiler-Taktkonfiguration
21
  TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate); // Auto-Reload
22
23
  // Timer Interruptkonfiguration
24
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                        // Interrupt bei Überlauf
25
  
26
  // Timer aktivieren
27
  TIM_Cmd(TIM2, ENABLE);
28
}
29
30
31
....
32
33
34
//***********************************************************************************************
35
// Timer 2 Interrupt-Handler
36
//***********************************************************************************************
37
void TIM2_IRQHandler(void) {
38
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
39
    // Überlauf des Zählregisters
40
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
41
  }
42
}

von Thomas B. (escamoteur)


Lesenswert?

Ich habs, ich hatte das Pending Bit im IRQ-Handler nicht zurückgesetzt. 
Komischerweise bekommt man dann trotzdem regelmäßige IRQs mit einer 
Dauer von 2µs. Eigentlich hätte ich erwartet, dass der Handler nur 
einmal angesprungen wird und dann nicht wieder bis das Pending Bit 
gelöscht wird.
Sobald man es löscht, bekomme ich auch längere Wartezeiten.

Wie passen eigentlich in dem Beispiel oben die 10ms zu den 10kHz im 
Code?

Gruß
Tom

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Siehe diese Zeile:
TIM_TimeBaseStructure.TIM_Period = 100;

von Thomas B. (escamoteur)


Lesenswert?

Ah, mit den 10kHz die Frequenz für eine Periode, daher 10kHz / 100 = 
100Hz
Ok, verstanden.

Ich hatte es so verstanden, dass der Timer-IRQ mit 10kHz ausgelöst 
werden sollte.
Gruß
Tom

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.