Forum: Mikrocontroller und Digitale Elektronik STM32F4 delay


von paule (Gast)


Lesenswert?

Guten Abend,

ich habe eine delay-Funktion für den STM32F4 soweit funktioniert.
Das Problem habe ich mit dieser Seite gelöst:
http://www.keil.com/pack/doc/cmsis/Core/html/group___sys_tick__gr.html
Ich hätte allerdings noch ein paar Fragen an euch.

1) Wie hoch ist die SystemCoreClock? Ich teile sie durch 1000 um eine ms 
zu erhalten, also 1s???
2) Habe ich einen Vorteil, wenn ich das mit dem SysTick_Handler mache, 
anstatt mit einem "normalem Timer" und dessen Interrupts?
1
#include <stm32f4xx.h>
2
3
uint32_t counter=0;
4
5
void init_LED(){
6
  //Anschalten der Taktversorgung für Port D
7
  RCC->AHB1ENR |= (1<<3);
8
  
9
  //Konfigurationsregister für den I/O-Port
10
  GPIOD->MODER |= (1<<24);
11
  GPIOD->MODER |= (1<<26);
12
}
13
14
void delay(int time){
15
  
16
  while(counter!=time){
17
  }
18
  
19
  counter=0;
20
}
21
22
void SysTick_Handler(void){
23
  counter++;
24
}
25
26
int main() {
27
  
28
  //Configure SysTick to generate an interrupt every millisecond 
29
  SysTick_Config(SystemCoreClock/1000);
30
31
  init_LED();
32
33
  do{
34
  
35
    GPIOD->BSRRL |= (1<<12);
36
    delay(6000);
37
    GPIOD->BSRRH |= (1<<12);
38
    delay(15000);
39
    
40
  } while(1);
41
  
42
}

von aSma>> (Gast)


Lesenswert?

paule schrieb:
> 1) Wie hoch ist die SystemCoreClock? Ich teile sie durch 1000 um eine ms
> zu erhalten, also 1s???

K.A. sag es du mir doch. Wer soll es wissen was du für einen pll 
eingestellt hast.

paule schrieb:
> 2) Habe ich einen Vorteil, wenn ich das mit dem SysTick_Handler mache,
> anstatt mit einem "normalem Timer" und dessen Interrupts?

Dafür ist der SysTick_Handler ja geschaffen!
1
paule schrieb im Beitrag #4544105:
2
> void delay(int time){
3
> 
4
>   while(counter!=time){
5
>   }
6
> 
7
>   counter=0;
8
> }

Vorsichtiger weise würde ich: uint32_t counter=0; als volatile 
deklarieren (kann counter je negativ werden?).

Weiterhin fehlt dir ein Bezugspunkt in der Zeit in deiner Schleife! Hier 
so geht es:
1
void delay(int time){
2
    uint32_t current_time = counter;
3
    while(counter-current_time<time);  //counter addiert in systick deshalt nennt man ihn sysTick_counter
4
}

so würde ich das aus dem Nähkästchen programmieren.

von Harry L. (mysth)


Lesenswert?

Die Frage der Fragen ist doch:
Warum muß es ein STM32F4xx sein, wenn man sich noch mit solchen 
Problemen herumplagen muß, und nicht mal den systick verstanden hat? 
(den es ja in Form von millis() bereits beim 8bit-Arduino gibt)

"Viel" hilft nicht immer viel...

von Jan H. (jan_h74) Flattr this


Lesenswert?

Die Systemclock wird initialisiert in die Function : System_init(). Der 
Aufruf und die Function sind in eine startup.s file definiert. Diese 
startup.s wird immer erst aufgerufen beim boot. Der µ startet immer mit 
seine interne oscillator (HSI), und dan soll System_init() laufen. Hier 
wird dan den clocktree eingestellt.

von paule (Gast)


Angehängte Dateien:

Lesenswert?

aSma>> schrieb:
> K.A. sag es du mir doch. Wer soll es wissen was du für einen pll
> eingestellt hast.

Ich habe mal meine Clock-Configuration angehängt. Meine SYSCLK ist 
24MHz, das ist aber nicht die System-Core-Clock oder? Die müsste doch 
bei 168MHz sein?

aSma>> schrieb:
> Dafür ist der SysTick_Handler ja geschaffen!

Das ist aber kein Vorteil im Gegensatz zu einer Delay-Programmierung mit 
einem "normalem" Timer und dessen Interrupt. Ich würde gerne wissen, 
warum ich den SystickHandler benutzen sollte anstatt eines 
TIM_InterruptHandlers?

von STMler (Gast)


Lesenswert?

paule schrieb:
> Ich habe mal meine Clock-Configuration angehängt. Meine SYSCLK ist
> 24MHz, das ist aber nicht die System-Core-Clock oder? Die müsste doch
> bei 168MHz sein?


Nö. Dafür stimmen PLL_M/N/Q nicht. Lies mal das Reference Manual.
Bei 2MHz Takt vor dem VCO ist übrigens der Jitter kleiner, daher sollte 
das eingestellt werden. Das im Manual steht nicht zum Spass da - auch 
wenn das auf so gut wie jeder Webseite falsch gemacht wird (schreibt da 
ein Seppel vom anderen ab und schaut keiner mehr ins Handbuch???)


> aSma>> schrieb:
>> Dafür ist der SysTick_Handler ja geschaffen!
>
> Das ist aber kein Vorteil im Gegensatz zu einer Delay-Programmierung mit
> einem "normalem" Timer und dessen Interrupt. Ich würde gerne wissen,
> warum ich den SystickHandler benutzen sollte anstatt eines
> TIM_InterruptHandlers?


"Sollte" ist falsch.
Der Systick hat zwei Vorteile:
1. Er ist simpel (und damit einfach zu konfigurieren)
2. Ihn gibt es in jedem Cortex-M, daher braucht die Software an der 
Stelle nicht geändert zu werden, wenn ein Wechsel stattfindet

von paule (Gast)


Lesenswert?

STMler schrieb:
> "Sollte" ist falsch.
> Der Systick hat zwei Vorteile:
> 1. Er ist simpel (und damit einfach zu konfigurieren)
> 2. Ihn gibt es in jedem Cortex-M, daher braucht die Software an der
> Stelle nicht geändert zu werden, wenn ein Wechsel stattfinden

Wird das Interrupt den SysTick_Handler höher priorisiert, als andere 
Interrupts? Das sollte doch Voraussetzung für eine gute/genaue delay 
Funktion sein.

von Vincent H. (vinci)


Lesenswert?

Wieso nimmst du nicht das von ST angebotene Tool "STM32CubeMX"?
Dort wird der SysClock automatisch für dich eingestellt...
Und die HAL Library bietet eine Delay-Funktion auf Basis des SysTicks.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

paule schrieb:
> Ich habe mal meine Clock-Configuration angehängt. Meine SYSCLK ist
> 24MHz, das ist aber nicht die System-Core-Clock oder? Die müsste doch
> bei 168MHz sein?

Doch, im Moment liegt Sysclk bei 24MHz.
Können wir mal verfolgen:
die HSI 16Mhz teilst du erstmal durch 16 (PLL_M) = 1Mhz. Dann wird sie 
in der PLL mit 192 (PLL_N) multipliziert = 192 Mhz. Zum Schluss teilst 
du durch 8 (PLL_P) = 24 Mhz.

Beachte das Datenblatt:
> The software has to set these bits correctly to ensure
> that the VCO output frequency is between 192 and 432 MHz
Du bist also am unteren Limit des VCO. Besser ist es, den VCO in der 
Mitte des Bereiches zu betreiben.
Also z.B. bei HSI = 16Mhz:
 PLL_M auf 8 für 2MHz zur PLL( siehe den Einwand von STMler, ist auch 
gut für stabile I2S Clocks). Dann mit PLL_N auf 168 = 336 Mhz VCO. Zum 
Schluss durch 2 teilen mit PLL_P = 2. Das Ergebnis sind die gewünschten 
168 Mhz Sysclk.

von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

das klingt alles nach "das Rad neu erfinden".
CubeMX installieren, einen gültigen Clocktree einstellen (lassen).

Systick nicht für Delay verwenden.

HAL_Delay(ms); ist schon fertig  von ST

Wenn es einen Delay <1ms braucht :
SystemCoreClock abfragen und eine
while(a<wasauchimmer){
a++;
}
einfügen.

HAL_GetTick(); kann auch nützlich sein.

>Wird das Interrupt den SysTick_Handler höher priorisiert, als andere
Interrupts?
kannst/musst du einstellen, siehe Bild. Je nach Cortex Variante mehr 
oder weniger Optionen.

>Das sollte doch Voraussetzung für eine gute/genaue delay Funktion sein.
Mag sein, aber die Notwendigkeit einer genauen Delay Funktion ist ein 
Beweis für schlechtes Software Design.
STM32 Callbacks und IRQs bei (erledigten/anstehenden) Ereignissen sind 
die Lösung.

Gruß,

dasrotemopped.

von dasrotemopped (Gast)


Lesenswert?

http://empa.com/dokumanlar/STM32Cube-presentation.pdf

http://empa.com/dokumanlar/STM32F4-Labs.pdf

So fällt der Einstieg in CubeMX leicht.

Gruß,

dasrotemopped.

von Meister Propper (Gast)


Lesenswert?

dasrotemopped schrieb:
> das klingt alles nach "das Rad neu erfinden".
> CubeMX installieren, einen gültigen Clocktree einstellen (lassen).


Nix für ungut, aber das klingt nach "Geländewagen in der Stadt fahren".

Aber das soll ja heutzutage Mode sein, wenn ich mir so all die SUVs vor 
dem Fenster ansehe...

Die 5 Seiten im Manual durchlesen und dann die paar Register zu 
beschreiben, sollte wohl keinen vor unlösbare Aufgaben stellen. Geht 
sicherlich schneller, als die Bloatware zu installieren.

von aSma>> (Gast)


Lesenswert?

Servus,

paule schrieb:
> Wird das Interrupt den SysTick_Handler höher priorisiert, als andere
> Interrupts? Das sollte doch Voraussetzung für eine gute/genaue delay
> Funktion sein.

Normalerweise setzt man den sysTick Handler auf die niedrigste 
Priorität.

Ich nutze oftmals den Systick um bestimmte Task in der main abzuspulen.
1
void SysTick_Handler(void)
2
{
3
  sysTick_ms++;
4
  if (!(sysTick_ms % TASK_TIME)) //taks alle 50ms, Haupttakt!
5
  {
6
     sysTick_b=1;          //in main for realtime
7
  }
8
  if (!(sysTick_ms % LCD_TIME))   //taks alle 1000ms
9
  {
10
     sysTick_lcd_b=1;  //Var muss volatile deklariert werden!!!
11
  }
12
}
13
14
main(){
15
if (sysTick_b == 1){
16
//task1
17
sysTick_b=0;
18
  
19
  if(sysTick_lcd_b == 1){
20
  //tastk2 ist hier untergeordnet
21
  sysTick_lcd_b=0;
22
  }
23
24
}

Vielleicht hat jemand bessere Ideen. Aber somit brauche ich keine extra 
timer zu setzen.

paule schrieb:
> void delay(int time){
>
>   while(counter!=time){
>   }
>
>   counter=0;
> }

Das wird so glaube ich nicht funktionieren! Was machst du, wenn counter 
größer als time ist? Auf den Tot warten?

Der Nachteil meiner Variante ist tatsächlich der Überlauf. Bei einer 
uint32_t var und 1ms Takt hat man nach 50 Tagen ein Problem. K.A. ob der 
µC weiter arbeitet oder abstürzt. Eine uint64_t hält dagegen eine 
Ewigkeit. Oder einfach mit eine zweite var mitzählen lassen und 
rücksetzen.

Die anderen Leute kommen mit der HAL Kacke an. So lernt man nichts. Aber 
kommt oftmals schneller zum Ziel.

Das ist halt so als würde man bei einen Date gleich zum Zug kommen ohne 
Langes Vorspiel.

mfg

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.