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_tcounter=0;
4
5
voidinit_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
voiddelay(inttime){
15
16
while(counter!=time){
17
}
18
19
counter=0;
20
}
21
22
voidSysTick_Handler(void){
23
counter++;
24
}
25
26
intmain(){
27
28
//Configure SysTick to generate an interrupt every millisecond
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
pauleschriebimBeitrag#4544105:
2
>voiddelay(inttime){
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
voiddelay(inttime){
2
uint32_tcurrent_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.
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...
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.
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?
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
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.
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.
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.
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.
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.
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
voidSysTick_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