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
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
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.
> 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
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
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.