Forum: Compiler & IDEs Unterprogramm abbrechen


von Dario C. (dario) Benutzerseite


Lesenswert?

Hallo Zusammmen,

irgendwie komme bei folgendem Problem ich nicht weiter:

Ich habe eine LED Lauflichtsteuerung. Die basiert auf vielen 
Unterprogrammmen, die jeweils ein Muster erzeugen und jeweils zwischen 
10 Sekunden und 10 Minuten laufen.

Jetzt habe ich Interruptgesteuert per Infrarot eine Empfangsroutine, die 
einen RC5-Code empfängt. Der Code soll gleich die Programmnummer sein.

In der Main sähe das dann so aus:
1
    while(1){
2
        if (prog == 1){
3
       snake();
4
        }
5
        if (prog == 2){
6
       schach();
7
        }
8
        if (prog == 3){
9
       laufschrift();
10
        }
11
    }

Mein Problem: Die IRQ speichert nach Empfang eines Codes diesen in 
"prog", aber das aktuelle Programm läuft ja noch.

Wie stelle ich es jetzt elegant an, dass die Unterprogramme abgebrochen 
werden, wenn ein neuer Code empffangen wurde?

Zur Zeit habe ich das wie folgt gelöst: Jedes Unterprogramm ruft immer 
die selben Funktionen (Delay und Framebuffer-Ausgabe) auf. Im Moment 
habe ich diese beiden Funktionen so gepatcht, dass Delay nach einem 
empfangenen Zeichen kein Delay macht und die Ausgabefunktion keine 
Ausgabe macht, aber die Unterprogramme laufen noch komplett durch, nur 
schneller.

Das muss doch irgendwie eleganter gehen, oder?

Hat hier jemand einen Tip für mich?

von Marius W. (mw1987)


Lesenswert?

Setze halt ein "Kill"-Flag, das die Unterprogramme regelmäßig prüfen. 
Wenn das Flag gesetzt ist, soll sich das Unterprogramm so schnell wie 
möglich beenden.

MfG
Marius

von Matthias L. (Gast)


Lesenswert?

du solltest das anders organisieren.

das main sollte etwa so aussehen:
1
while(1)
2
{
3
4
  switch (prog)
5
  {
6
  case 1:
7
    snake();
8
    break;
9
  case 2:
10
    schach();
11
    break;
12
  }
13
14
}


Dein IR-COde schreibt das aktuelle Programm in prog und ruft das 
permanent auf. Du musst die Lauflicht-funktionen so programmieren, dass 
diese immer nur durchlaufen und beendet werden können. 
(Zustandsautomaten verwenden!)

von Dario C. (dario) Benutzerseite


Lesenswert?

Hallo nochmal,

@Matthias:
>   switch (prog)
>   {
>   case 1:
>     snake();
>     break;
>   case 2:
>     schach();
>     break;
>   }

Naja, das behebt nicht das problem und technisch ist das kein großer 
Unterschied.

> Dein IR-COde schreibt das aktuelle Programm in prog und ruft das
> permanent auf. Du musst die Lauflicht-funktionen so programmieren, dass
> diese immer nur durchlaufen und beendet werden können.
> (Zustandsautomaten verwenden!)

Toll, so habe ich das im Prinzip ja auch, aber ich hatte mal irgendwo 
was gelesen, wo jemand das mit sowas wie LONGJUMP oder so versucht hat.

Alternativ könnte man auch ein OS einsetzen und die einzelnen Tasks 
einfach abschießen, aber ob das nicht wie mit Kanonen auf Spatzen 
schießen ist weiß ich nicht.

Deswegen: Weiß jemand wie man in diesem Zusammenhang LONGJUMP einsetzen 
kann?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

longjmp würde ich nicht einsetzen, das wär mir zu viel Hack ;-) vor 
allem aus einer ISR heraus...

In meiner Scope-Clock habe ich ein ähnliches Problem: einerseits gibt es 
komplexe Darstellungsroutinen (Snake, Asteroids, ...) andererseits muss 
auf Eingaben reagiert werden und in genau festgelegten Zeitabständen der 
Elektronenstrahl positioniert werden.

Das hab ich so gelöst, daß das Zeichnen in einer ISR stattfindet. Die 
Vorberechnungen hingegen geschehen im Hauptprogramm in 
nichtblockierenden Routinen. Wenn du irgendwo delay-Geraffel 
verwendest oder auf Timer wartest, hast du schon verloren.

Im Hauptprogramm gibt es Handler für die verschiedenen Menüpunkte 
(Spiele, etc.) mit Routinen die zB einen neuen Frame berechnen. Die 
Darstellung bzw. Interpretation geschieht jedoch in einer ISR.

von Karl H. (kbuchegg)


Lesenswert?

Dario C. schrieb:

> Deswegen: Weiß jemand wie man in diesem Zusammenhang LONGJUMP einsetzen
> kann?

Das willst du eigentlich nicht wirklich.

Für dein Problem gibt es 2 Lösungsansätze

Der eine ist der pragmatische, den man bei dir jetzt zum Einsatz bringen 
kann, weil der Rest schon fertig ist.

Der andere ist der, den du von vorne herein hättest gehen sollen.


Der pragamtische geht so:
Jedes deiner Unterprogramme prüft in regelmässigen Zewitabständen ob die 
'Abbruch-Variable' gesetzt wurde und kehrt ins Hauptprogramm zurück.

Der andere Weg besteht darin, dass ein Muster nicht ein einziges 
'komplexes' UNterprogramm ist sondern, dass im Hauptprogramm nach 
jeweils x Millisekunden dem gerade aktiven Muster die Chance gegeben 
wird, einen 'Musterschritt' zu machen. Danach muss das jeweilige 
Unterprogramm sofort zurückehren und die Kontrolle so wieder abgeben.
Eine bewährte Organisationsform wurde weiter oben schon genannt: Ein 
Zustandsautomat.

Eine andere Möglichkeit besteht darin, einen Weg zu suchen, wie man 
jedes Muster einfach nur durch Daten beschreiben kann, der 
Ausführungsteil, der das Muster aus diesen Daten dann letztendlich 
erzeugt, aber immer derselbe ist.
Sprich: Ein einziger Programmcode erzeugt nur durch Austausch von Daten 
(zb in einzelnen Arrays) die verschiedenen Muster.

von sven (Gast)


Lesenswert?

Könnte man nicht aus der ISR einen REset ausführen und beim Neustart 
'prog' (darf natürlich nicht überschrieben werden bei der 
Initialisierung) auswerten ?

von Qwertz (Gast)


Lesenswert?

>Könnte man nicht aus der ISR einen REset ausführen und beim Neustart
>'prog' (darf natürlich nicht überschrieben werden bei der
>Initialisierung) auswerten ?

Könnte man. Ist aber völlig unnötig wenn man es "richtig" macht, d.h. so 
wie Karl Heinz es beschrieben hat.

von Dario C. (dario) Benutzerseite


Lesenswert?

Naja, dann lasse ich es also alles so wie es ist.

- In den Unterprogrammen wird regelmäßig ein KILL-FLAG ausgewertet und
  wenn gesetzt das Unterprogramm abgebrochen.
- Die Ausgaberoutinen geben nix aus, wenn das KILL-FLAG gesetzt ist.
- Die Delay-Funktion mach kein delay mehr, wenn das KILL-FLAG gesetzt 
ist.

Nicht sexy, aber funktioniert.

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.