switch:case durch Interrupt unterbrechen

Gast #2660107
Lesenswert?

Hallo, ich bin gerade am programmieren.

In meinem Programm gibt es eine switch:case Anweisung. Diese würde ich 
gerne durch einen Interrupt unterbrechen lassen, bzw. durch den 
Interrupt direkt in einen bestimmten Zustand springen lassen.

z.B.

switch(A)

case 1:
case 2:
case 3:
case 4:
case 5:

In Case 3 findet ein Interrupt statt, wodurch er sofort in Case 4: 
springt. Wenn ich den Zustand im Interrupt setzte, bleibt das Programm 
hängen, aber warum?
Also Interrupt und Programm an sich funktioniert, wurde getestet.
Eine Möglichkeit währe es noch im Interrupt z.b. T=1 setzen und in den 
einzelnen Cases abfragen. Allerdings springt er dann nicht sofort in den 
richtigen Case, und ab 10,15 cases wird das auch einiges an unnützen 
Codes.
Habt ihr vlt. eine Idee?
Gast #2660113
Lesenswert?

Kannst du nicht eine variable setzen (oder den Case ändern), die 
Select-Anweisung mit einem Break beenden und halt aussenrum ne do 
while-Schleife setzen?

Das verändern der variablen dann auch am besten in eine kleine sub, so 
hast du pro case ein/zwei Zeilen mehr code.
Gast #2660137
Lesenswert?

A. K. schrieb:
> Für mehr Hilfe müsste man mehr über das Problem wissen.

Was musst du noch mehr wissen? Ich habe 10 Cases, in einem davon findet 
ein Interrupt statt. Findet dieser statt, soll in einen bestimmten Case 
gesprungen werden. Was brauchst du noch für Infos? Und warum 
Schwarzpulver? Was ist daran so gefährlich, verkehrt...?
#2660147
Lesenswert?

YunPe schrieb:

> Ich habe 10 Cases, in einem davon findet
> ein Interrupt statt.

Um mit dieser Beschreibung etwas anzufangen müsste ich deinen Kopf 
aufsägen und reinsehen, sorry. Da musst du schon etwas mehr ausholen.

Interrupts sind meisten kein Bisschen synchron mit dem Hauptprogramm, 
sondern geschehen an beliebiger Stelle.

> Schwarzpulver? Was ist daran so gefährlich, verkehrt...?

Aus einem Interrupt-Handler unter Umgehung des normalen 
Rückkehrverfahrens ins Hauptprogramm zu springen ist keine Lösung, 
sondern ein Problem.
Gast #2660153
Lesenswert?

Ok, dann nochmal genauer....

Ich habe 10 Cases, die laufen ganz normal ab,... Dann wird z.B. durch 
einen Taster ein externer Interrupt ausgelöst. Durch diesen Interrupt 
soll sofort, egal in welchem Case er gerade arbeitet zum Case 9 
gesprungen werden. ... Hoffe das reicht.
#2660162
Lesenswert?

Das reicht um festzustellen, dass dieser Ansatz nicht sinnvoll ist. 
Entweder erledigst du die Aktion "case 9" direkt im Interrupt-Handler, 
oder du baust den Code im Hauptprogramm so um, dass er auf eine vom 
Handler entsprechend gesetzte Variable reagiert.

Denk ausserdem dran, dass Taster prellen.
Gast #2660167
Lesenswert?

Also direkt im Case9 erledigen ist schlecht, da dass Hauptprogramm ja 
nicht weitermachen soll, wenn Interrupt.

An das mit dem Handler hab ich auch gedacht, aber dann eben der 
zusätzliche Code. Dachte, bzw. hätte mir gewünscht, dass es so auch 
geht. Also dass der Interrupt einfach sagt,..so jetzt Case9. Schade.
#2660215
Lesenswert?

YunPe schrieb:
> Also direkt im Case9 erledigen ist schlecht, da dass Hauptprogramm ja
> nicht weitermachen soll, wenn Interrupt.
>
> An das mit dem Handler hab ich auch gedacht, aber dann eben der
> zusätzliche Code. Dachte, bzw. hätte mir gewünscht, dass es so auch
> geht. Also dass der Interrupt einfach sagt,..so jetzt Case9. Schade.

Es sieht wohl so aus, dass der ganze Ansatz mies ist.
Jede Wette, da sind wieder mal Warteschleifen und _delay_ms und 
dergleichen im Spiel.

Für eine vernünftige Lösung müsste man wohl das komplette Programm 
kennen, die Aufgabenstellung kennen und da erst mal einen gscheiten 
Ansatz austüfteln, das vorhandene Programm wegwerfen und das alles 
vernünftig und sauber nach den Regeln der Kunst machen.

Und diese Lösung funktioniert dann auch.
Gast #2660234
Lesenswert?

Also ich erledige dergleichen eigentlich immer mit einer funktion 
"CyclicTests", bei der eben ständig (meist hat man ja eh n haufne 
schleifen) gewisse Flags, welche durch Interrupts und Zähler beeinflusst 
werden, abgefragt werden.

Klar bedeutet das mehr code, aber wer mehr Funktion braucht, braucht 
halt mehr code.

Selbst wenns manchmal etwas "ungeschickt" über ISR setzt variable 
DoBreak=True und dann muss man halt an entsprechender Stelle im Programm 
ein

If DoBreak=TRUE then
break
end if

einbauen.

PRozedurale Programmierung bedingt halt manchmal ein geknödel, vor allem 
wenn sinnvoll auf Interrupts reagiert werden soll.

Was so schlimm an den paar Zeilen mehr (10 Cases, 3 Zeilen= 30 Zeilen 
mehr code, ist das so schlimm?) sein soll, verstehe ich auch nicht. Ich 
würde da ganz klar der Funktion der Vortritt vor der Eleganz lassen.
Gast #2660250
Lesenswert?

YunPe schrieb:
> An das mit dem Handler hab ich auch gedacht, aber dann eben der
> zusätzliche Code. Dachte, bzw. hätte mir gewünscht, dass es so auch
> geht. Also dass der Interrupt einfach sagt,..so jetzt Case9. Schade.

Klar geht das. In der ISR die auf dem Stack liegende Rücksprungadresse 
durch die von case 9: ersetzen, fertig.

Aber: Vergiß das ganz schnell wieder. Solche Spielchen sind 
grundsätzlich und immer ein Zeichen für ein völlig ungeeigneten 
Programmkonzeptes.

DAS MACHT UND BRAUCHT MAN NICHT, ausser, man schreibt Kernel für 
Echtzeitbetriebssysteme, oder was in der Art, und deine Frage lässt 
erahnen, daß du das nicht vorhast.

Oliver
#2662405
Lesenswert?

Zeig endlich dein komplettes Programm.

Der Witz in der µC Programmierung besteht darin, dass es nur EINE 
dauernd laufende Schleife gibt.

int main()
{
   ....

  while( 1 ) {

     .... // B
  }
}


dies ist die einzige Schleife, die ständig läuft. Wenn da an der Stelle 
B ein switch case existiert, dann ist das ok. Aber: Deine ganze 
Fragestellung stellt sich nicht! Denn es besteht keine Notwendigkeit da 
von einem 'case' zu einem anderen zu springen. Man verändert die Werte 
für die switch-Abfrage und beim nächsten Durchlauf durch die Schleife 
wird dann eben ein anderer case genommen.

Schon alleine dadurch, dass du diese Frage überhaupt stellst, drängt 
sich die Vermutung auf, dass du da bei irgendeinem case eine Schleife 
hast. Und die ist das Problem. Die muss da weg.
#2662406
Lesenswert?

Hallo,

die "Statemachine" wird immer erst bis zum Ende ausgeführt, bis beim 
nächsten Durchlauf neue Ereignisse zu einem anderen Zustand führten und 
somit sich die Programmausführung in diesem Zustand abläuft.

D.h. das externe Ereignis kommt erst ein paar µs später zum 'Zuge'.

Ereignisse (Events) könnte:
- Interrupts,
- ADC Wanderergebnisse,
- Zeit Events oder
- Tastenevents
- z.B. neue logische Ereignisse sein.

Die Darstellung stellt nur eine mögliche Aufschlüsselung von einfachen 
bis komplexen Events dar !

Für die Konstruktions einer "Statemachine" gibt es verschiedene 
Methoden.

Z.B. ein Zustandsdiagramm und auf den Pfeilen dann die Ereignisse oder 
ein Petrie-Netz um komplexere reale "Welt"-Strukturen zu beschreiben..

Genaueres lies bitte über Google oder Wikipedia nach.

ok ?
#2662420
Lesenswert?

Und nochwas:
Wenn du jetzt wieder mit einer verbalen Beschreibung kommst, wie die 
Dinge deiner Meinung nach laufen müssen, dann schmeiss ich dich raus.

Entweder du machst jetzt Nägel mit Köpfen und bringst was, mit dem man 
auch arbeiten kann oder du lässt es bleiben. In letzterem Fall bist du 
aber beratungsresistent und damit ist es sinnlos, wenn jemand noch was 
dazu schreibt. Denn dann willst du keine vernünftige Lösung sondern nur 
irgendwie deinen verkorsten Ansatz retten.

Deine ganzen Beschriebungen lssen bei allen hier die Alarmglocken 
klingen, dass in Wirklichkeit dein ganzes Programmkonzept verkorkst ist! 
Sowas lässt sich meistens nicht mit 1 oder 2 Zeilen Code hier und da 
korrigieren, sondern das muss man sich konkret komplett ansehen, die 
Aufgabenstellung analysieren und mit etwas Neuem hochkommen. Aber 
diesmal richtig und nicht wieder Murks.
Gast #2662427
Lesenswert?

YuPe schrieb:
> Aber diese wird doch auch
> per switch case realisiert und somit ergibt sich das gleiche Problem.
> Oder habe ich da jetzt was falsch verstanden?

Der Witz bei der Reaktion auf einen Tastendruck in einem 
Mkrocontrollerprogramm liegt darin, daß das nicht "sofort" passiern muß. 
sondern in aller Ruhe an einer passenden Stelle im Programm zu einem 
passenden Zeitpunkt. Da sdauert zewar dann einige ms, aber das merkt 
kein Mensch.

Oliver
#2662510
Lesenswert?

@  YuPe (Gast)

>per switch case realisiert und somit ergibt sich das gleiche Problem.

nein.

>Oder habe ich da jetzt was falsch verstanden?

Ja. Die state machine bleibt nicht in den case Zweigen stecken sondern 
läuft da sehr schnell durch. Wenn jetzt ein Ereignis in einer ISR 
festgestellt wird, setzt dieses eine Variable, aka Flag. Diese wird beim 
nächsten Durchlauf der state machine ausgewertet und wenn es denn sein 
soll springen alle State in State x. Nix Stackmanipulation, alles ganz 
ordentlich.
Gast #2664429
Lesenswert?

Ok, dank für die vielen Tips. Werd jetzt versuchen, das Programm ohne 
switch:case hinzubekommen. Bzw. Richtung Statemachine.
Werde mich dann wieder melden, sollte das nicht gelingen werde ich mein 
programm posten. Würde es gern zuerst ein bisschen selbst probieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren