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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von OP (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Wait Klasse erzeugen und so oft instanzieren
wie man sie braucht.

von Klassenletzter (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Klassen in C?

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


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert

von Laberkopf (Gast)


Bewertung
-1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von Markus M. (adrock)


Bewertung
0 lesenswert
nicht 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:

Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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 ;-))))

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.