STM32 Timer will nicht so wie ich es will

OP #2266684
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
#2266706
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.
#2266742
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
}
OP #2267273
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren