Forum: Mikrocontroller und Digitale Elektronik STM32F4 Timer konfigurieren


von STM32Einsteiger (Gast)


Lesenswert?

Moin,
hab mir jetzt schon ein paar Threads angeschaut, aber irgendwie wird 
meine Frage nicht so richtig beantwortet.

Folgendes liegt vor:
-STM32F4 Discovery
-CooCox
-Standard Periphal Library
-Takt 168MHz (PLL und alles schön eingestellt)
-Timer 2

Ich würde gerne einfach die blaue LED im 1s Takt blinken lassen. Ich 
steige aber einfach nicht durch die Einstellung des Timers durch, also 
wie müssen Prescaler gesetzt werden etc..
1
  TIM_TimeBaseInitTIM.TIM_ClockDivision = 1;
2
  TIM_TimeBaseInitTIM.TIM_CounterMode = TIM_CounterMode_Up;
3
  TIM_TimeBaseInitTIM.TIM_Period = 1000000;
4
  TIM_TimeBaseInitTIM.TIM_Prescaler = 84-1;
5
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitTIM);

Gibt es da nicht eine Formel wo man die Werte eintragen kann und man 
dann die Freuqenz/Zeit bekommt?

von Jahat (Gast)


Lesenswert?

Hallo,

Basistakt des Timers anschauen TIM2
Herz = 1
Tim2Takt = 84000000
Prescaler = 10000/Herz
Periode = Tim2Takt/Prescaler

sollte bei einer Sekunde ankommen wenn ich nicht zu besoffen bin

Gruß J.

von Ingo (Gast)


Lesenswert?

Ich hoffe du meinst Hertz?



Ingo

von STM32Einsteiger (Gast)


Lesenswert?

Jahat schrieb:
> sollte bei einer Sekunde ankommen wenn ich nicht zu besoffen bin
>
> Gruß J.

Habe die nun wie folgt eingestellt:
1
        TIM_TimeBaseInitTIM.TIM_ClockDivision = TIM_CKD_DIV1;
2
  TIM_TimeBaseInitTIM.TIM_CounterMode = TIM_CounterMode_Up;
3
  TIM_TimeBaseInitTIM.TIM_Period = 8400;
4
  TIM_TimeBaseInitTIM.TIM_Prescaler = 10000;
5
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitTIM);

Die Interrupt Routine sieht so aus:
1
void TIM2_IRQHandler(void){
2
  if(GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_15)){
3
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, RESET);
4
    }else{
5
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, SET);
6
      //USART3_SendString("Test\n");
7
    }
8
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
9
}

Die LEDs blinkt nicht, bzw. so langsam das man es nicht sieht. Sobald 
ich die usart Routine reinpacke sieht man ein blinken, aber auch nur 
weil die usart Routine so langsam ist und die LED länger an lässt ...

Habe auch kein Oszi da um mir den Pin mal anschauen zu können. Irgendwie 
läuft mein Board zu schnell.

Ist das so richtig eingestellt? Oder habe ich noch was vergessen?
1
#if !defined  (HSE_VALUE) 
2
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
3
#endif /* HSE_VALUE */
Auf dem Discovery ist ja ein 8MHz Quarz verbaut.
1
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
2
#define PLL_M      8
3
#define PLL_N      336

Laut Rechnung kommt auch 168MHz raus.

Irgendwas muss ich vergessen bzw. übersehen haben weshalb die LED zu 
langsam bzw. zu schnell blinkt?!

von STM32Einsteiger (Gast)


Lesenswert?

STM32Einsteiger schrieb:
> abe auch kein Oszi da um mir den Pin mal anschauen zu können. Irgendwie
> läuft mein Board zu schnell.

Meinte zu langsam ...

von Thomas W. (diddl)


Lesenswert?

Bist du sicher dass der F4 mit 168MHzb taktet?


Ich musste bei den CooCox Dateien einige Korrekturen durchführen fürs 
Discovery:

+ 8MHz Quartz statt wie eingestellt 25MHz

+ INIT wird nicht aufgerufen, deshalb ist der PLL auf 20MHz statt 168MHz

von Thomas W. (diddl)


Lesenswert?

Hier hast du ein CooCox/Discovery F4 Demo von mir, das unter anderem die 
vier LED blinken lässt:

xs1541.t-winkler.net/zip/Zoomfloppy/Stm32F407_blink_06.zip


Neben der Blinkerei wird auch das SDIO (bzw. eine SD Karte) getestet und 
der USART 2 initialisiert und benutzt.



Wenn am USART ein Terminal hängt kommt in etwas sowas:

### Discovery 32F4 Demo ###


PCLK1:   42000000
PCLK2:   84000000
SYSCLK:  168000000
-----------------
initialize SDIO system ...
drive 0 ok
3869984 KB total drive space.
3871744 KB available.
SDIO system ok, free clusters: 120937
--- read/write test
Zeile 1
Zeile 2
Zeile 3
textfile test ok.
--- reading directory
D1541II.BIN
DOS1541.BIN
TRKCACHE.BIN
D.D64
TEST.TXT
TEST2.TXT
BASEN.D64
EXASS.D64
TAXI.D64
<SPIELE>
<APPS>

von STM32Einsteiger (Gast)


Lesenswert?

Thomas Winkler schrieb:
> Bist du sicher dass der F4 mit 168MHzb taktet?

Inzwischen bin ich mir da schon nicht mehr so sicher ...

> Ich musste bei den CooCox Dateien einige Korrekturen durchführen fürs
> Discovery:
>
> + 8MHz Quartz statt wie eingestellt 25MHz

Wie oben gezeigt habe ich das eingestellt.

> + INIT wird nicht aufgerufen, deshalb ist der PLL auf 20MHz statt 168MHz

Wenn du die "SystemInit();" meinst, dann ist diese vorhanden.

Zum testen hab ich jetzt eine delay Fuktion eingebaut
1
void delay(volatile uint32_t delay_time){
2
    while (delay_time > 0) {
3
        delay_time--;
4
    }
5
}

Normalerweise müsste ja bei delay_time = 168.000.000 eine Verzögerung 
von ca. 1s auftreten oder? Wenn ich den Wert lasse dauert die 
Verzögerung aber so ziemlich genau 10s. Mach ich den Wert entsprechend 
um 10 kleiner , also delay_time = 16.800.000, dann habe ich so ziemlich 
genau 1s.

Irgendwo muss dieser Faktor drin stecken. Ich vermute daher, dass der 
Takt 16,8MHz ist, ich werde mal schauen ob ich irgendwo eine 0 zu viel 
oder zu wenig habe ...

von STM32Einsteiger (Gast)


Lesenswert?

Thomas Winkler schrieb:
> Hier hast du ein CooCox/Discovery F4 Demo von mir, das unter anderem die
> vier LED blinken lässt:
>
> xs1541.t-winkler.net/zip/Zoomfloppy/Stm32F407_blink_06.zip
>
>
> Neben der Blinkerei wird auch das SDIO (bzw. eine SD Karte) getestet und
> der USART 2 initialisiert und benutzt.

Hab das Packet mal compiliert. Da scheinen zwei Dateien zu fehlen:
1541.h und EvalBoard.h.

Bisher danke soweit für deine Bemühungen :)

von Thomas W. (diddl)


Lesenswert?

Eigentlich müsste es sich unter CooCox 1.5 fehlerfrei kompilieren 
lassen. Bei mir sind einige Dateien vom Build ausgenommen.

Habe gerade kein CooCox zur Hand, ich schau mir das abends an.

von Thomas W. (diddl)


Lesenswert?

übrigens sollten auch binaries dabei sein ...

von STM32Einsteiger (Gast)


Lesenswert?

Thomas Winkler schrieb:
> übrigens sollten auch binaries dabei sein ...

Auf die Idee bin ich auch gerade gekommen. Folgende Meldung bekomme ich:
### Discovery 32F4 Demo ###


PCLK1:   42000000
PCLK2:   84000000
SYSCLK:  168000000
-----------------
initialize SDIO system ...
failed to execute f_getfree(). rc=3

liegt wohl daran, dass ich keine SD Karte dran habe. Mit deinem Projekt 
scheint der Takt auch richtig zu laufen.

Werd mal deine Diagnose Funktion in mein Projekt kopieren und schauen 
welche Werte der mir ausspuckt.

von Uwe (Gast)


Lesenswert?

> Wenn du die "SystemInit();" meinst, dann ist diese vorhanden.
Ja aber wo wird Sie aufgerufen. Vorhandensein alleine reicht nicht, die 
muß auch von irgendwo aufgerufen werden.

von Thomas W. (diddl)


Lesenswert?

Klar muss eine SD Karte da sein. Blinken die LED's nicht trotzdem?


Falls nicht, - in der main() kannst du einfach die SDIO Sachen 
auskommentieren.

von STM32Einsteiger (Gast)


Lesenswert?

Thomas Winkler schrieb:
> Klar muss eine SD Karte da sein. Blinken die LED's nicht trotzdem?

Jop die blinken schön.

Uwe schrieb:
> Ja aber wo wird Sie aufgerufen. Vorhandensein alleine reicht nicht, die
> muß auch von irgendwo aufgerufen werden.

Wird als ganz erstes in der main(); aufgerufen.

Ich bin davon überzeugt, dass der Fehler was ganz banales ist. Was ich 
aber mit meiner Umwissenheit nicht finde ...
Daher hier nochmal der komplette Quelltext:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_rcc.h"
3
#include "stm32f4xx_gpio.h"
4
#include "stm32f4xx_usart.h"
5
#include "stm32f4xx_tim.h"
6
#include "misc.h"
7
#include "usart.h"
8
9
void delay(volatile uint32_t cycles) {
10
  while(cycles > 0){
11
    cycles--;
12
  }
13
}
14
15
void TIM2_IRQHandler(void){
16
  if(GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_15)){
17
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, RESET);
18
    }else{
19
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, SET);
20
      USART3_SendString("Test");
21
    }
22
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
23
}
24
25
int main(void) {
26
  // Inititalisieren
27
  SystemInit();
28
29
  // USART konfigurieren
30
  USART3_Config();
31
32
  // Takt für PortD einschalten
33
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
34
35
  // Strukturen festlegen
36
  GPIO_InitTypeDef GPIO_InitGPIO;
37
38
  // Pin Parameter einstellen
39
  GPIO_InitGPIO.GPIO_Pin = (GPIO_Pin_15|GPIO_Pin_14);
40
  GPIO_InitGPIO.GPIO_Mode = GPIO_Mode_OUT;
41
  GPIO_InitGPIO.GPIO_OType = GPIO_OType_PP;
42
  GPIO_InitGPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
43
  GPIO_InitGPIO.GPIO_Speed = GPIO_Speed_50MHz;
44
45
  // Port initialisieren
46
  GPIO_Init(GPIOD, &GPIO_InitGPIO);
47
48
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTIM;
49
  NVIC_InitTypeDef NVIC_InitStructure;
50
51
  // Takt für Timer2 einschalten
52
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
53
54
  // Timer 2 konfigurieren
55
  TIM_TimeBaseInitTIM.TIM_ClockDivision = TIM_CKD_DIV1;
56
  TIM_TimeBaseInitTIM.TIM_CounterMode = TIM_CounterMode_Up;
57
  TIM_TimeBaseInitTIM.TIM_Period = 8400;
58
  TIM_TimeBaseInitTIM.TIM_Prescaler = 10000;
59
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitTIM);
60
61
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
62
63
  // Timer Interrupt konfigurieren
64
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
65
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
66
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
67
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
68
  NVIC_Init(&NVIC_InitStructure);
69
70
  // Timer starten
71
  TIM_Cmd(TIM2, ENABLE);
72
73
    while(1) {
74
    }
75
}

von Jo D. (Firma: Jo) (discovery)


Lesenswert?

Ändere diese Interruptfunktion hier ab:
1
void TIM2_IRQHandler(void){
2
  if(GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_15)){
3
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, RESET);
4
    }else{
5
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, SET);
6
      USART3_SendString("Test");
7
    }
8
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
9
}

In das hier:
1
void TIM2_IRQHandler(void){
2
 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
3
  if(GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_15)){
4
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, RESET);
5
    }else{
6
      GPIO_WriteBit(GPIOD, GPIO_Pin_15, SET);
7
      USART3_SendString("Test");
8
    }
9
 
10
}


////////////////////////////////////////////////////////////////////////

Wenn die obige Änderung keinen Erfolg bringt, so habe ich hier noch 
einen Beispielcode für dich:
1
//-------------------------------------------STM32F4_TIMER_INTERRUPT-------------------------------------------------------
2
3
/* Beschreibung:
4
 * Ein Timer erzeugt einen Interrupt und eine LED blinkt
5
 */
6
/*
7
8
Hinweis zum Clock fuer 8MHz Quarz, damit er auf 168MHz läuft (betrifft das stm32F4Discovery):
9
10
in der system_stm32f4xx.c muss eingetragen sein:
11
PLL_M = 8
12
13
in der stm32f4xx.h muss eingetragen sein:
14
HSE_VALUE = 8000000
15
*/
16
17
#include "stm32f4xx.h"
18
#include "stm32f4xx_gpio.h"
19
#include "stm32f4xx_rcc.h"
20
#include "stm32f4xx_tim.h"
21
#include "misc.h"
22
23
24
volatile uint32_t timer_tick;
25
26
void GPIO_INIT_EXAMPLE(void)
27
{
28
  GPIO_InitTypeDef  GPIO_InitStructure;
29
30
  /* GPIOD Periph clock enable */
31
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
32
33
  /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
34
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_14;
35
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
36
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
37
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
38
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
39
  GPIO_Init(GPIOD, &GPIO_InitStructure);
40
}
41
42
void TIMER_INIT_EXAMPLE(void)
43
{
44
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
45
46
  // Der Timer wird mit 84MHz getaktet (APB1 Domain mit 42MHz X2 siehe Seite 85 im Ref.Man.)
47
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
48
  // Time Base initialisieren
49
  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
50
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
51
  TIM_TimeBaseInitStructure.TIM_Prescaler = 10000-1;
52
  TIM_TimeBaseInitStructure.TIM_Period = 8400 - 1;
53
  TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
54
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
55
56
  // Interrupt enable für Update
57
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
58
59
  // um den Timer loslaufen zu lassen
60
  TIM_Cmd(TIM2,ENABLE);
61
}
62
63
void NVIC_INIT_EXAMPLE(uint16_t IRQ)
64
{
65
  NVIC_InitTypeDef NVIC_InitStructure;
66
67
  NVIC_InitStructure.NVIC_IRQChannel = IRQ;
68
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
69
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Die Priorität --> kleine Zahlen = hohe Priorität
70
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
71
  NVIC_Init(&NVIC_InitStructure);
72
}
73
74
void TIM2_IRQHandler(void)
75
{
76
  while( (TIM2->SR & (1<<0)) > 0 ) TIM2->SR &= ~(1<<0); // clear UIF flag
77
  timer_tick++;
78
}
79
80
81
int main(void)
82
{
83
84
  SystemInit();
85
86
  TIMER_INIT_EXAMPLE();
87
88
  NVIC_INIT_EXAMPLE(TIM2_IRQn);
89
90
  GPIO_INIT_EXAMPLE();
91
92
93
  while(1)
94
    {
95
96
    ////////////////////////timer_tick////////////////////////
97
    if (timer_tick >= 5)
98
    {
99
      GPIOD->ODR ^= GPIO_Pin_14; // Toggle LED
100
      timer_tick = 0;
101
    }
102
    ///////////////////////////////////////////////////////////
103
    }
104
}

von STM32Einsteiger (Gast)


Lesenswert?

Jo discovery schrieb:
> Ändere diese Interruptfunktion hier ab ...

WTF! Es geht! :D
Vielen Dank an euch!!!

Und warum löst diese banale Änderung das Problem?!

von Jo D. (Firma: Jo) (discovery)


Lesenswert?

STM32Einsteiger schrieb:
> Jo discovery schrieb:
>> Ändere diese Interruptfunktion hier ab ...
>
> WTF! Es geht! :D
> Vielen Dank an euch!!!
>
> Und warum löst diese banale Änderung das Problem?!

Weil das Interruptflag eine Weile benötigt bis es gelöscht ist und somit 
noch nach Verlassen der Interruptroutine aktiv ist.

Merke: Das Interruptflag immer ganz am Anfang der Interruptroutine so 
früh wie möglich löschen!

von STM32Einsteiger (Gast)


Lesenswert?

Jo discovery schrieb:
> Weil das Interruptflag eine Weile benötigt bis es gelöscht ist und somit
> noch nach Verlassen der Interruptroutine aktiv ist.
>
> Merke: Das Interruptflag immer ganz am Anfang der Interruptroutine so
> früh wie möglich löschen!

Gut zu wissen.

Hab das mit den Timer, dann doch kapiert gehabt. Die 
Ursprungseinstellung des Timers funktioniert auch mit der Änderung. Was 
ganz oben zu sehen ist, war die pure Verzweiflung und Ausprobierwut.

Danke nochmal an euch! :)

von Jahat (Gast)


Lesenswert?

Ingo schrieb:
> Ich hoffe du meinst Hertz?
> Ingo

Jup...   schäm  
bin aber im Zuge dessen über ein nettes Tutorial gestolpert 
www.mySTM32.de

hertzlichst J.

von Alex A. (Gast)


Lesenswert?

Hallo!

Wollte kein neuen Thread für meine Frage aufmachen.
Habe mir vor paar Tagen einen STM32F429 Evalboard mit LCD gekauft.
Gleich einzelne Peripherie in Betrieb genommen.

Leider funktionieren immer die einfachsten Sachen nicht :)
Aktuell benutze ich den SDRAM und LCD.
Nun brauche ich noch den Timer Interrupt. Genau dieser läuft nicht.

Die ganzen Beispiele, die ich gefunden habe, machen eine LED an und aus.
Das sollte als Grundlage sicherlich reichen, aber irgendwie läuft das 
nicht.
GPIO brauche ich nicht, ich will nur, dass der Timer IRQ ausgelöst wird.
Wenn jemand mit mehr erfahrung da mal drüberschauen könnte, wäre das 
schon eine große Hilfe. Sitze da schon seit 8 Stunden :( Total peinlich 
sowas :)

Bis auf das Wesentliche gekürzt:
1
#include "main.h"
2
#include "stm32f4xx_conf.h"
3
#include "stm32_ub_lcd_ili9341.h"
4
#include "stm32_ub_graphic2d.h"
5
#include "stm32_ub_font.h"
6
#include "stm32f4xx_tim.h"
7
#include "stm32f4xx_rcc.h"
8
#include "stm32f4xx.h"
9
#include "misc.h"
10
#include "stm32f4xx_gpio.h"
11
12
13
int main(void)
14
{
15
16
  TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
17
  NVIC_InitTypeDef NVIC_InitStructure;
18
19
  SystemInit(); 
20
21
// Timer IRQ
22
  void TIM2_IRQHandler(void){
23
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
24
      }
25
26
27
28
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
29
30
  TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
31
  TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
32
  TIM_TimeBase_InitStructure.TIM_Period = 1999;
33
  TIM_TimeBase_InitStructure.TIM_Prescaler = 17999;
34
  TIM_TimeBaseInit(TIM2, &TIM_TimeBase_InitStructure);
35
36
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
37
38
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
39
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
40
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
41
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
42
  NVIC_Init(&NVIC_InitStructure);
43
44
  TIM_Cmd(TIM2, ENABLE);
45
46
  while(1)
47
  {
48
49
  }
50
51
}

Wie gesagt, ich benutze den LCD und SDRAM, nicht, dass da sich mit dem 
Timer IRQ was überschneidet.
Der Code lässt sich soweit compilieren, aber z.B. LCD funktioniert dann 
nicht mehr. Kommentiere ich der Timercode aus, läuft alles wieder.


Vielen Dank!

Gruß
Alex S.

von holger (Gast)


Lesenswert?

Was soll der Interrupthandler da mitten in der main()?

von Alex A. (Gast)


Lesenswert?

Oh, nein!!!!
Danke! :)

von Harald B. (haraldino)


Lesenswert?

ich hatte mal in excel ein Timer Code Generator für den STM32 
geschrieben.

Vielleicht findet ihn ja hier jemand.

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.