Jetzt habe ich ein Interrupt im Hintergrund, welches alle 1ms aufgerufen
wird.
Nach tue_was(); muss ich aber mindestens 1ms warten..
Wie löse ich das Problem am Besten?
pasi schrieb:> Moin,>> zum Beispiel nach tue_was_was() die Interrupts sperren.>> Gruß
Ich muss aber alle 1ms im Interrupt unbedingt etwas machen, zB
multiplexen. Ausschalten ist also leider keine gute Idee.
>> Jetzt habe ich ein Interrupt im Hintergrund, welches alle 1ms aufgerufen> wird.
Aha. Warum hast du diesen Interrupt?
> Nach tue_was(); muss ich aber mindestens 1ms warten..
Warum sollte das Warten einen Konflikt mit dem Interrupt ergeben? Das
Hauptprogramm wartet an dieser Stelle doch trotz des Interrupts. Ich
kenne den HAL Krempel nicht wirklich, aber vermutlich hält es die eine
Millisekunde sogar nur wegen des Interrupts ein.
Und falls das wirklich einen Konflikt darstellen sollte, warum
aktivierst du den Interrupt dann überhaupt?
> Wie löse ich das Problem am Besten?
Durch selber denken.
Ist am Anfang vielleicht ungewohnt, hilft langfristig aber am besten.
Die normale Implementierung von HAL_Delay() ist doch, dass eine Variable
im Vergleich zu SysTick gezählt wird. Damit SysTick funktioniert lauft
der SysTick Interrupt. HAL_Delay() hält keine Interrupts an.
Ich würde zwar auch den 1ms Takt mittels SysTick steuern, aber wenn das
ein anderer Interrupt ist, dann sollte das alles trotzdem wie gewünscht
funktionieren.
Ok, dann habe ich zunächst mal eine andere Frage.
Von welchem Delay ist hier die Rede?
https://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR
Es heisst hier nämlich:
um beispielsweise eine LED blinken zu lassen. Will man dann noch andere
Dinge erledigen, wundert sich der Programmierer, warum der
Mikrocontroller so langsam reagiert, trotz 16 MHz Taktfrequenz.
Habe ich also mit HAL_Delay kein Problem, dass mir die Interrupts nicht
reagieren?
Axel S. schrieb:> Fragender schrieb:> Durch selber denken.> Ist am Anfang vielleicht ungewohnt, hilft langfristig aber am besten.
Hallo Axel
Glaub mir das habe ich getan, aber komme auf keinen grünen Zweig. Wenn
das nämlich der Fall ist, frage ich erfahrene wie euch.
Interrupts sind von der delay Funktion nicht betroffen. Das ist ja der
Sinn der Interrupts. Sie unterbrechen das Hauptprogramm, ganz egal was
es gerade tut.
Die Delays werden aber stören, wenn du Multitasking ohne Interrupts
programmierst.
Fragender schrieb:> Ok, dann habe ich zunächst mal eine andere Frage.>> Von welchem Delay ist hier die Rede?
Nein, zuerst beantwortest du uns bitte mal eine Frage, die schon in
deinem Anfangsposting hätte klar sein sollen:
Von welchem Prozessor redest du?!?
HAL_Delay() ist typisch bei ARM-Prozessoren und verwendet eine intern
durch einen Interrupt hochgezählte Variable.
> https://www.mikrocontroller.net/articles/Multitasking#Ein_einfaches_Beispiel_f.C3.BCr_den_AVR>> Es heisst hier nämlich:
Warum kommst du mit AVR-Informationen? Ist es doch kein ARM?
Fragender schrieb:> Ok, dann habe ich zunächst mal eine andere Frage.> Von welchem Delay ist hier die Rede?
Nicht von HAL_Delay(). Denn das ist eine Funktion aus der HAL Library
für STM32 Controller. Im genannten Artikel geht es im AVR Controller.
> Habe ich also mit HAL_Delay kein Problem, dass mir die Interrupts nicht> reagieren?
Ich habe keine Ahnung, wovon du redest. Was meinst du mit "Interrupts
nicht reagieren"?
> Axel S. schrieb:>>> Durch selber denken.>> Ist am Anfang vielleicht ungewohnt, hilft langfristig aber am besten.>> Glaub mir das habe ich getan, aber komme auf keinen grünen Zweig.
Das glaube ich dir unbesehen. Außerdem glaube ich, daß du das Konzept
Interruptnicht verstanden hast. Dann würdest du nämlich diese
Fragen nicht stellen. Fang damit an. Das ist essentiell. Du kannst
keinen µC programmieren, wenn du Interrupts nicht verstehst.
Fragender schrieb:> Habe ich also mit HAL_Delay kein Problem, dass mir die Interrupts nicht> reagieren?
Was hindert dich daran, das selber festzustellen?
Damit du die Sache verfolgen kannst, gibt es genug Möglichkeiten. Du
könntest den Code im Simulator deiner IDE verfolgen, z.B. indem du an
strategischen Stellen Breakpoints setzt, du könntest ähnlich die
möglicherweise vorhandene Debugmöglichkeit deines µC nutzen, du könntest
mit einem kleinen Logikanalysator und ein paar passend eingestreuten
Ausgaben auf GPIOs den Gang der Dinge angucken, du könntest mit längeren
Delays() und Ausgabe auf LEDs die Sache visuell verfolgbar machen.
Reicht das nicht?
Wie wir sehen, wird hier wie empfohlen der Systick Timer verwendet. Die
funktion wird die korrekte Zeit abwarten, auch wenn sie zwischenzeitlich
durch Interrupts unterbrochen wurde.
Ganz anders die Funktion _delay_ms() von der AVR libc:
1
void_delay_loop_2(uint16_t__count)
2
{
3
__asm__volatile(
4
"1: sbiw %0,1""\n\t"
5
"brne 1b"
6
:"=w"(__count)
7
:"0"(__count)
8
);
9
}
10
11
void_delay_ms(double__ms)
12
{
13
uint16_t__ticks;
14
__tmp=((F_CPU)/4e3)*__ms;
15
if(__tmp<1.0)
16
__ticks=1;
17
elseif(__tmp>65535)
18
{
19
// __ticks = requested delay in 1/10 ms
20
__ticks=(uint16_t)(__ms*10.0);
21
while(__ticks)
22
{
23
// wait 1/10 ms
24
_delay_loop_2(((F_CPU)/4e3)/10);
25
__ticks--;
26
}
27
return;
28
}
29
else
30
__ticks=(uint16_t)__tmp;
31
_delay_loop_2(__ticks);
32
}
Hier wird kein Timer verwendet, sondern eine gewisse Anzahl von CPU
Zyklen vertrödelt. Wenn diese Schleife durch Interrupts unterbrochen
wird, verlängert sich ihre Zeitspanne entsprechend über die gewünschte
Zeit hinaus.
Stefanus F. schrieb:> Wie wir sehen, wird hier wie empfohlen der Systick Timer verwendet. Die> funktion wird die korrekte Zeit abwarten, auch wenn sie zwischenzeitlich> durch Interrupts unterbrochen wurde.
Nicht "auch wenn". Die Funktion ist sogar auf den Systick-Interrupt
angewiesen. Ohne den Interrupt würde HAL_GetTick() immer den gleichen
Wert zurück liefern und HAL_Delay() würde ewig warten.
Ich frage mich ja immer noch, wie man überhaupt auf die Idee kommen
kann, eine Warteschleife (ganz egal ob mit Timer oder busy wait) würde
durch einen Interrupt abgebrochen. Die einzige Erklärung die mir
einfällt, wäre wie gesagt daß das Konzept Interrupt nicht verstanden
ist.
Ja und?
Wenn ich sowieso einen 1 ms-Interrupt habe, dann brauch ich
doch kein xyz-delay(), wobei das Hauptprogramm blockiert ist.
Und wenn es zu ungenau ist, nehme ich einen 0,1
oder 0,01 ms-Interrupt, der wohl genug Auflösung für's delay()
bieten sollte. Die eigentlichen 1 ms-Aufgaben führt er dann
halt nur bei jedem 10. (100.) Aufruf durch...
Erst mal die Resourcen im Kopf nutzen, dann braucht es meist
deutlich weniger Resourcen beim µC. - Oder der µC schafft dann
noch deutlich mehr.