Forum: Mikrocontroller und Digitale Elektronik STM32, nichtblockierendes Warten, Systick, Funktion in C?


von OP (Gast)


Lesenswert?

Ein Programm im STM32 soll an bestimmten Stellen warten, um zB Timeouts 
zu realisieren oder periodisch Aktionen auszuführen. Das Warten darf 
nicht blockieren (Also nicht einfach delay). Dafür kann ich gut den 
Systick Timer benutzen, der zB jede Millisekunde einen Zähler 
inkrementiert. Im Programm kann ich zu gegebener Zeit den Zählerstand 
speichern und damit bei den nächsten Durchläufen die verstrichene 
Wartezeit ermitteln, und zwar auch, wenn sehr viele Funktionen 
gleichzeitig warten sollten.
1
if(systickcounter>systickcounter_old+PERIOD)
2
{
3
    systickcounter_old = systickcounter;
4
  
5
    //Do your thing
6
}
Wie kann ich sowas in eine Funktion verpacken, die ich beliebig oft 
parrallel von verschiedenen Stellen aus im Code aufrufen kann? 
Prinzipiell muss ja bei jedem neuen Aufruf eine neue Instanz erzeugt 
werden, die eine eigene systickcounter_old-Variable hat, bzw jeder 
Aufrufer braucht seine eigene Instanz.
1
if(wait(PERIOD))
2
{
3
    //Do your thing
4
}

von Klassenletzter (Gast)


Lesenswert?

Wait Klasse erzeugen und so oft instanzieren
wie man sie braucht.

von Klassenletzter (Gast)


Lesenswert?

Also etwa so:
--------------
1
wait.startwait(time);  // initialisiert einen Wait-Vorgang
2
3
while (wait.checkwait() != TIMEOUT)  // check ob Zeit schon abgelaufen
4
{
5
    //Do your thing
6
}

von OP (Gast)


Lesenswert?

Klassen in C?

Beitrag #4978030 wurde von einem Moderator gelöscht.
von Bernd K. (prof7bit)


Lesenswert?

Klassenletzter schrieb:
> Wait Klasse erzeugen

Ne simple Variable tuts auch um sich die Startzeit zu merken. Und ob man 
das eine kleine if() nun als nacktes if() direkt hinschreibt oder als 
Aufruf einer Funktion die nur existiert um ein einziges if() zu 
beinhalten oder gar als einen Aufruf einer Methode eines Objekts das nur 
für den einen Zweck existiert ein Feld und eine Methode zu haben die nur 
dem Zweck dient eine einzige winzige kleine Zeile mit einem einzigen 
if() zu "abstrahieren", mithin also drölfzig und nochmal zwei Zeilen 
Boilerplate um ein einziges if() zu kapseln oder das eine if() direkt 
hinzuschreiben ist reine Geschmackssache.

Machen wir doch mal die Bilanz:

OP: 1 Variable und 1 if()

Du: 1 Objektinstanz und immer noch ein if() (oder while) um das Ergebnis 
des gekapselten ursprünglichen if() abzufragen das jetzt irgendwo anders 
sein Dasein fristet.

: Bearbeitet durch User
von Laser (Gast)


Lesenswert?


von Laberkopf (Gast)


Lesenswert?

Laser schrieb:
> Hier wird das schoen erklärt:

Ein Käse wird da erklärt, völlig nicht-relevant zum Thema.

von Franz (Gast)


Lesenswert?

>Ein Käse wird da erklärt, völlig nicht-relevant zum Thema.

Das zeigt, dass du es nicht gelesen hast. Es wird genau das erklärt was 
er braucht.
Allerdings muss er natürlich noch den SysTick Counter in die Funktion 
millis() wrappen.
Falls das zu schwierig ist, empfehle ich eher Häkeln als Hobby.

von Laberkopf (Gast)


Lesenswert?

Franz schrieb:
> Falls das zu schwierig ist, empfehle ich eher Häkeln als Hobby.

Ja mir ist das Labern schon zu schwierig.

von Franz (Gast)


Lesenswert?

Hier die Zusammenfassung des Artikels:

> We’ve learned how to time things using millis() instead of delay()
> so we can free up the processor to do other things.

> We’ve learned how to define tasks as state machines that can execute
> independently of other state machines at the same time.

> And we’ve learned how to encapsulate these state machines
> into C++ classes to keep our code simple and compact.

Jetzt noch die Hausaufgaben für den STM-User:
- schreiben sie die Funktion millis() welche den SysTick Counter 
ausliest und den Wert als long int zurück gibt.
- die Beispiele nutzen Servos und LEDs. Beantworten Sie die Frage, ob 
auch andere Funktionen genutzt werden können.
- Überlegen Sie sich weitere Klassen und schreiben Sie Beispiele

https://learn.adafruit.com/multi-tasking-the-arduino-part-1/conclusion

von RP6conrad (Gast)


Lesenswert?

In C mache ich das so : In den interrupt handler von Systick verwende 
ich eine Variable (volatile !)  für ein "Timer" :
void SysTick_Handler(void)
{
if (Delay != 0x00) Delay--;
milli_seconds++;cal_timer++;speed_timer++;watchdog_gps++;
MPU_print++;timer_0++;mpu_timer++;Tx_timer++;
}

In main wird das dan so gemacht :
if(milli_seconds>100){milli_seconds=0;do_stuff();}

von Bernd K. (prof7bit)


Lesenswert?

Und natürlich sollten in diesem Themenkomplex auch die Protothreads 
nicht unerwähnt bleiben: Beitrag "Wer benutzt Protothreads?"

von Markus M. (adrock)


Lesenswert?

...wenn man bei C bleiben möchte, kann man eine Art Klasse auch so 
programmieren:

- Datenstruktur "timer" definieren
- Funktionen schreiben, die mit dieser Datenstruktur arbeiten, wobei 
jeweils beim Aufruf ein Zeiger auf die Datenstruktur übergeben wird
- Datenstruktur beliebig oft instaniziieren und dann mit den Funktionen 
verwenden

Abhängig davon wie genau die Intervalle sein sollen, könnte diese timer 
Bibliothek auch die einzelnen "timer" in einer Liste verwalten und dann 
im systick Interrupt bearbeiten (checken ob Timer abgelaufen etc).

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

OP schrieb:
> Wie kann ich sowas in eine Funktion verpacken, die ich beliebig oft
> parrallel von verschiedenen Stellen aus im Code aufrufen kann?

garnicht. Mach es genau anders herum.

1. schreibe dir eine Systemuhr, die die Uhrzeit in ms zählt.
1a. ordne dort auch ne stupide Warterei ein, für den Fall, daß irgendwas 
ein Warten benötigt, bevor die Uhr komplett aufgesetzt ist.

2. lasse diese Systemuhr eine Liste führen, wo Ereignisse eingetragen 
werden können, die zu einer bestimmten Uhrzeit in Erscheinung treten 
sollen. Dazu gehört: Liste bei jedem (oder jedem 10. oder so) Timertick 
durchsehen und Ereignis ggf. werfen, Liste zu Mitternacht zusammen mit 
der Uhrzeit um 24h zurücksetzen, Methode zum Listeneintrag, Methode zum 
löschen eines Ereignisses aus der Liste.

3. schreibe dir eine kleine Ereignisverwaltung. Also Definition von 
Ereignissen, Ereignis-Warteschlange, Methoden zum einwerfen von 
Ereignissen in die Warteschlange und zum Auslesen der Warreschlange.

4. frage in deiner Grundschleife die Ereigniswarteschlange ab und 
reagiere, wenn du dort ein Ereignis findest. Etwa so:
1
 if(EventAvailable())
2
 { switch (GetEvent())
3
   case evMachsLichtAus: MachsLichtAus(); 
4
                         AddDelayedEvent(evMachTürZu,5000); // nach 5 sek
5
                         break;
6
   case evTürklingel:    SiehNach(Haustür);
7
   };
8
 }
Das war's.
Ich hänge dir mal was dran, was du seit Jahren auch schon in der 
Lernbetty hättest finden können.

W.S.

von Huch (Gast)


Lesenswert?

Bernd K. schrieb:
> Ne simple Variable tuts auch um sich die Startzeit zu merken. Und ob man
> das eine kleine if() nun als nacktes if() direkt hinschreibt oder als
> Aufruf einer Funktion die nur existiert um ein einziges if() zu
> beinhalten oder gar als einen Aufruf einer Methode eines Objekts das nur
> für den einen Zweck existiert ein Feld und eine Methode zu haben die nur
> dem Zweck dient eine einzige winzige kleine Zeile mit einem einzigen
> if() zu "abstrahieren", mithin also drölfzig und nochmal zwei Zeilen
> Boilerplate um ein einziges if() zu kapseln oder das eine if() direkt
> hinzuschreiben ist reine Geschmackssache.
>

Cool ;-))))

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.