Forum: Mikrocontroller und Digitale Elektronik Frage zu delay


von Fragender (Gast)


Lesenswert?

Ich möchte folgendes tun:
1
void start()
2
{
3
  
4
tue_was();
5
HAL_Delay(1);  
6
tue_was2();
7
8
}


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?

von pasi (Gast)


Lesenswert?

Moin,

zum Beispiel nach tue_was_was() die Interrupts sperren.

Gruß

von Fragender (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

1
// delay 1s
2
uint32_t start=HAL_GetTick();
3
while (HAL_GetTick()-start<1000);

von Axel S. (a-za-z0-9)


Lesenswert?

Fragender schrieb:
> Ich möchte folgendes tun:
>
>
1
> tue_was();
2
> HAL_Delay(1);
3
> tue_was2();
4
>
>
> 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.

von Marten Morten (Gast)


Lesenswert?

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.

von Purzel H. (hacky)


Lesenswert?

Ich wuerde gleich den Timerinterrupt zum Warten verwenden

von Fragender (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Marten Morten (Gast)


Lesenswert?

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?

von Axel S. (a-za-z0-9)


Lesenswert?

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 
Interrupt nicht 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.

von my2ct (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

Das ist der Quelltext von HAL_Delay für STM32F1:
1
__weak void HAL_Delay(uint32_t Delay)
2
{
3
  uint32_t tickstart = HAL_GetTick();
4
  uint32_t wait = Delay;
5
6
  /* Add a freq to guarantee minimum wait */
7
  if (wait < HAL_MAX_DELAY)
8
  {
9
    wait += (uint32_t)(uwTickFreq);
10
  }
11
12
  while ((HAL_GetTick() - tickstart) < wait)
13
  {
14
  }
15
}

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
  else if (__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.

von Axel S. (a-za-z0-9)


Lesenswert?

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.

: Bearbeitet durch User
von Jacko (Gast)


Lesenswert?

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.

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.