Forum: Mikrocontroller und Digitale Elektronik STM32F07VG Discovery - Timer + Sleep


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Robin H. (robin_h319)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich fange gerade an mich mit dem STM32F407 zu beschäftigen. Vorher habe 
ich öfters den MSP430G2553 und Arduino programmiert.

Ich bin gerade auf der Suche nach einem simplen Code Beispiel und blicke 
bei dem STM32 noch nicht ganz durch.

Ich möchte eigentlich etwas ähnliches wie ich es beim MSP430 oder 
Arduino umgesetzt habe:


init();
while(1){
  // programm laufen lassen
  // interrupts einschalten
  // enter sleep mode
  // interrupts ausschalten
  // ggf. flag bearbeiten
}

ISR(TIMERX_XY_vect){
  // flag setzen
  // ggf. LPMX_bits + GIE beim exit ausschalten
}

Interrupts alle x ms mit TIM3 hinbekommen ist kein Problem - dafür gibt 
es ja genügend Beispiele. Nur mit den Sleep Modes klappt es leider 
nicht.. Oder wird die Clock im Sleep Mode für den TIM3 ausgeschaltet?

Ich habe es mit PWR_EnterSTANDBYMode(); probiert.

Grüße,
Robin

von Robin H. (robin_h319)


Bewertung
0 lesenswert
nicht lesenswert
Hier noch etwas Code dazu - ist im endeffekt eins der Examples zu TIM 
die man in der Atollic IDE findet. Das was fehlt, wäre das Betreten 
eines LPM
1
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
2
TIM_OCInitTypeDef  TIM_OCInitStructure;
3
__IO uint16_t CCR1_Val = 54618;
4
__IO bool TIM3_flag = false;
5
uint16_t PrescalerValue = 0;
6
7
void initTimer(void);
8
9
int main(void)
10
{
11
    // other init stuff
12
    initTimer();
13
    TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
14
    TIM_Cmd(TIM3, ENABLE);
15
16
    while (1)
17
    {
18
      if (TIM3_flag == true){
19
                // do stuff
20
        TIM3_flag = false;
21
      }
22
        // do stuff
23
24
    }
25
}
26
27
void initTimer(void){
28
  // Init GPIOD
29
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
30
  GPIO_InitTypeDef  GPIO_InitStructure;
31
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
32
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
33
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
34
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
35
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
36
  GPIO_Init(GPIOD, &GPIO_InitStructure);
37
  GPIO_SetBits(GPIOD,GPIO_Pin_14);
38
39
  // Init interrupt
40
  NVIC_InitTypeDef NVIC_InitStructure;
41
42
  /* TIM3 clock enable */
43
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
44
45
  /* Enable the TIM3 gloabal Interrupt */
46
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
47
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
48
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
49
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
50
  NVIC_Init(&NVIC_InitStructure);
51
52
  /* Compute the prescaler value */
53
  PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 500000) - 1;
54
55
  /* Time base configuration */
56
  TIM_TimeBaseStructure.TIM_Period = 65535;
57
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
58
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
59
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
60
61
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
62
63
  /* Prescaler configuration */
64
  TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);
65
66
  /* Output Compare Timing Mode configuration: Channel1 */
67
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
68
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
69
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
70
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
71
72
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
73
74
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
75
}


und aus der ISR:
1
uint16_t capture = 0;
2
extern __IO uint16_t CCR1_Val;
3
extern __IO bool TIM3_flag;
4
5
void TIM3_IRQHandler(void)
6
{
7
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
8
  {
9
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
10
11
    TIM3_flag = true;
12
13
   capture = TIM_GetCapture1(TIM3);
14
    TIM_SetCompare1(TIM3, capture + CCR1_Val);
15
  }
16
}

Kann ich den TIM3 in verbindung mit sleep modes überhaupt nutzen? Wenn 
ja, wie muss ich die Sleep modes einstellen.

Danke für die Hilfe

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Robin H. schrieb:
> Nur mit den Sleep Modes klappt es leider
> nicht.. Oder wird die Clock im Sleep Mode für den TIM3 ausgeschaltet?

Versuch's doch erstmal mit dem einfachsten Sleep Mode, bei dem nur der 
Prozessor-Kern abgeschaltet wird:
1
__WFI ();
oder
1
__asm__ volatile ("wfi");
Dabei bleiben alle zuvor aktivierten Peripherie-Einheiten an, und der 
Prozessor wacht bei Interrupts wieder auf.

Robin H. schrieb:
> if (TIM3_flag == true){
>                 // do stuff
>         TIM3_flag = false;
>       }
Bei den ARM's kannst du die eigentliche Verarbeitung auch problemlos in 
der ISR machen, du musst nicht Flags setzen und das in der main() 
machen. Indem du anderen Interrupts eine höhere Priorität zuweist, 
können die eventuell lange laufende andere ISR's unterbrechen - somit 
ist die "Regel", keine langen Verarbeitungen in der ISR zu machen, 
hinfällig. Die main() sieht dann nur noch so aus:
1
int main () {
2
  // Initialisierungen ...
3
  __enable_irq (); // Interrupts ein
4
  while (1) {
5
    __WFI (); // Schlafen
6
  }
7
}
Und der Rest kommt in die ISR's. Das entspricht dann einer 100% 
asynchronen Programmierung.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
> Oder wird die Clock im Sleep Mode für den TIM3 ausgeschaltet?

Kommt auf den konkreten Sleep Modus an. Siehe 
http://stefanfrings.de/stm32/index.html#power

: Bearbeitet durch User
von Robin H. (robin_h319)


Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Versuch's doch erstmal mit dem einfachsten Sleep Mode, bei dem nur der
> Prozessor-Kern abgeschaltet wird:__WFI ();oder__asm__ volatile
> ("wfi");Dabei bleiben alle zuvor aktivierten Peripherie-Einheiten an,
> und der
> Prozessor wacht bei Interrupts wieder auf.

Super, danke. Mit __WFI(); hat sofort geklappt!

Dr. Sommer schrieb:
> Indem du anderen Interrupts eine höhere Priorität zuweist,
> können die eventuell lange laufende andere ISR's unterbrechen - somit
> ist die "Regel", keine langen Verarbeitungen in der ISR zu machen,
> hinfällig.

Werde ich mir mal anschauen. Bin gerade dabei Interrupts mit 
Statemachines (Yakindu State Chart Tools) zu verbinden und möchte eine 
möglichst "hardware unabhängige" Lösung erarbeiten, quasi ne Art 
Template/Pattern. Vielleicht sollte ich bei ARM's einen anderen Ansatz 
wählen.

Viele Grüße und Danke,
Robin

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Robin H. schrieb:
> Vielleicht sollte ich bei ARM's einen anderen Ansatz
> wählen.

Würde ich gar nicht - State Machines kann man wunderbar in ISR's packen, 
und in einem Interrupt immer jeweilig auf die entsprechenden Ereignisse 
reagieren und den Zustand ändern. Wenn du im Interrupt gar nichts machst 
außer Flags zu setzen, kannst du die ISR auch ganz weglassen, und die 
Interrupt-Flags direkt in der main() abfragen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.