STM32, nichtblockierendes Warten, Systick, Funktion in C?

Gast #4977986
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
}
Gast
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
}
Beitrag #4978030 wurde von einem Moderator gelöscht.
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.
Gast
>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.
Gast
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
Gast
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();}
...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).
Gast
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.
Angehängte Dateien:
Gast
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 ;-))))

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.