Forum: Mikrocontroller und Digitale Elektronik Statemaschine mit Sprung oder ähnlich.gibt oder geht so was


von Peter C. (Gast)


Lesenswert?

Hallo zusammen,
bei der Weiterentwicklung meines Projektes stosse ich an einen Punkt an 
dem ich jetzt den 4.Tag hänge. Ich muß dazu sagen mit "C" arbeite zwar 
schon ein paar Tage, habe aber noch so meine Probleme wie Ihr lesen 
könnt.

zu den Randbedingungen:
Mit einem Taster/ auf Tastendruck zähle ich die Variable Modul je eins 
hoch. Mit einer switch case verzweige ich auf die jeweilige zuständige 
Funkion. Das geht bei Modul 0 los und endet bei Modul 4. Wenn alle ADC 
Pinne belegt sind geht alles perfekt.

void Modulwahl (int Modul){
   switch (Modul){
   case 0 : EIMSK &= ~(1<<INT2);
     break;
   case 1 : Modul_1_init();
     break;
   case 2 : Modul_2_init();
      break;
   case 3 : Modul_3_init();
    break;
   case 4 : Modul_4_init();
   break;
   default:
   break;
  }
}

Da nicht von Anfnag an alle Modulanschlüsse (ADC) belegt werden können, 
möchte ich die belegten ADC mit Jumper quasi frei/aufschalten. Modul 0 
und 1 bleiben aber ohne Jumper und sind so immer anwählbar.
So werte ich nach hochtasten der Variable "Modul" auch den zuständigen 
Jumper aus. Wenn jetzt z.B. Jumper 2 und 3 aber nicht gesetzt sind soll 
die Auswertung dies bemerken und den nächsten belegten ADC anspringen.
Nach mehrfachem Tastendruck also vom Start mit Modul 0 nach Tastendruck 
auf Modul 1 und nach weiterem Tastendruck Modul 2 und 3 überspringen (da 
Jumper nicht gesetzt) und Modul 4 anspringen
Genau da hänge ich, ich habe einiges mit if, Else und elseif probiert 
komme aber nicht weiter.
So habe ich angefangen, wenn der Jumper 2 gesteckt ist und die Variable 
Modul den Wert 2 enthält dann springe in die Funktion Modulauswahl und 
initialisiere Modul 2.

if ((!IS_RESET(LDA_Jumper)) && (Modul == 2)){
     Modulwahl(Modul);
   }

else {
      Modul++;
}

ansonsten wenn die Bedingung nicht erfüllt ist zähle die Variable Modul 
+1 hoch und prüfe erneut.
Ganau da hänge ich,  ...prüfe erneut...Hirnwindungskurzschluss.....ich 
brauch da mal einen Tipp, vielleicht habe ich mich da auch in einer 
Auswertemöglichkeit verrant die nicht zielführend ist. Kann man einfach 
zurück an den Anfang der Auswertgun zurück springen ??.
Ich werde das ganze nochmal auf einem Blatt skitzzieren...ein Tipp wäre 
super.

Achja ich verwende einen ATMega1284P mit 16MHZ, AVR Studio 4.19

Danke
Peter

von kopfkratzer (Gast)


Lesenswert?

Kopfkratz
Was willst Du nun, entweder alle ADC-Eingänge sind der Statemachine 
entsprechend belegt oder nicht.
Entweder Du paßt Deine Statemachine an Dein Problem an oder Du nutzt 
grundsätzlich alle ADCs ...
Ist eigentlich ganz einfach, zuerst die Jumper in der Statemachine 
einbinden und in die Übergänge übernehmen ...

von picbastler (Gast)


Lesenswert?

Mein Ansatz wäre so: Modul nicht "um eins hochzählen", sondern "so weit 
hochzählen (ggf. mit Überschlag), bis ein sinnvoller Wert erreicht ist". 
Dann erst wieder Modulwahl aufrufen.

Also z.B. so:
1
Modul = FindNext(Modul);
2
Modulwahl(Modul);

Jetzt brauchst du nur noch eine schöne Funktion, die dir den nächsten 
sinnvollen Wert bestimmt.
1
int FindNext(int Modul)
2
{
3
  bool Ok = 0;
4
  while (!Ok) {
5
    Modul += 1;
6
    switch(Modul) {
7
      case 0: // 0 und 1 sind immer anwählbar
8
      case 1:
9
        Ok = 1;
10
        break;
11
      case 2: // 2 ist nur anwählbar, wenn Jumper gesetzt  
12
        if (JUMPER_SET(2)) {
13
          Ok = 1;
14
        }
15
      case 3: // 3 mag z.B. von einer anderen Bedingung abhängen
16
        if (ANDERE_BEDINGUNG) {
17
          Ok = 1;
18
        }
19
      default:
20
        // wir sind einmal durch, zurück zum Start
21
        Modul = 0;
22
        Ok = 1;
23
    }
24
  }
25
  return Modul;
26
}

von xfr (Gast)


Lesenswert?

Wenn man schon ein Case-Statement mit allen Möglichkeiten hat, kann man 
da auch gleich den Modul_x_init()-Aufruf reinpacken. In etwa so:
1
switch (Modul) {
2
  case 0: // geht immer
3
    Modul = 1;
4
    Modul_1_init();
5
    break;
6
  case 1: // 2 ist nur anwählbar, wenn Jumper gesetzt  
7
    if (JUMPER_SET(2)) {
8
      Modul = 2;
9
      Modul_2_init();
10
      break;
11
    }
12
  case 2: // 3 mag z.B. von einer anderen Bedingung abhängen
13
    if (ANDERE_BEDINGUNG) {
14
      Modul = 3;
15
      Modul_3_init();
16
      break;
17
    }
18
  case 3:
19
    [...]
20
  case 4: // am Ende muss ein Fall stehen, der immer geht
21
    Modul = 0;
22
    EIMSK &= ~(1<<INT2);
23
    break;
24
  }
25
}

von Peter C. (Gast)


Lesenswert?

Hallo zunächst schonmal dankr für die Antworten.

@ Kopfkratzer: wenn alles ganz einfach wäre würde ich nicht nach 4 Tagen 
mit diversen Versuchen hier fragen.

Die beiden anderen Antworten werde ich mir heute Abend anschauen und 
nochmal überdenken.


@ picbastler
Ich habe in der Switch noch nie probiert einen "case" mit und andere 
ohne break zuverlassen. Mit break verlasse ich die ganze switch und ohne 
würde er dann die nächste case anspringen sofern wie hier das 
Modul(wert) passt ????? ist das so ????

das sind doch Tipps !!

Peter

von picbastler (Gast)


Lesenswert?

Also, in meinem Beispiel habe ich die "breaks" bei case 2, 3 und default 
einfach vergessen. Sie gehören dort ganz normal hin.

Ohne break läuft er einfach weiter in den nächsten case hinein, das hast 
du richtig erkannt. Das kann durchaus auch Sinn machen (wie bei xfr zu 
sehen). In schreibe dort aber gerne nochmal explizit "no break" dazu, um 
Missverständnisse zu vermeiden.

Der Vorschlag von xfr funktioniert auch und ist sicher am kompaktesten, 
aber da muss man gerade als Anfänger wirklich zweimal hinschauen, um zu 
verstehen, was da passiert. Meine sehr persönliche Meinung wäre: lieber 
ein bißchen mehr Coding hinschreiben, das man dann aber auch nachts um 3 
noch versteht.

von Peter C. (Gast)


Lesenswert?

Hallo,
ich kann dem Codeing schon folgen....das ist nicht mein Problem sondern 
wenn ich eben in der Modulfolge z.B. 2 und 3 nicht gejumpert habe dann 
sol er einfach weiter springen bis der nächste gesetzte Jumper kommt 
oder es eben wieder bei "0" von vorn weiter geht.

Grundeinstellung     Modulvar = 0 -> Ini Modul 0

Taster gedrückt   -> Modulvar = 1 -> Ini Modul 1

Taster gedrückt   -> Modulvar = 2
                       |
                       |-> Abfrage Jumper=ja und Modulvar=2 ->Ini Modul2

                       |-> Wenn Jumper= nein dann Modulvar +1
                       also automatisch auf Modulvar 3 springen und
                       Jumper 3 auswerten. Ist der Jumper gesetzt dann
                       ini Modul 3 sonst Modulvar +1 usw.....

Wenn also keiner der drei Jumper gestzt ist drücke ich mit dem Taster 
von 0 auf 1 und dann mit nächtem tasten (sprung 2 - 3- 4 unbemerkt) 
wieder auf 0.

ich glaube ich bilde gerade ein Hirnödem.

Peter

von Falk B. (falk)


Lesenswert?

>So werte ich nach hochtasten der Variable "Modul" auch den zuständigen
>Jumper aus. Wenn jetzt z.B. Jumper 2 und 3 aber nicht gesetzt sind soll
>die Auswertung dies bemerken und den nächsten belegten ADC anspringen.
>Nach mehrfachem Tastendruck also vom Start mit Modul 0 nach Tastendruck
>auf Modul 1 und nach weiterem Tastendruck Modul 2 und 3 überspringen (da
>Jumper nicht gesetzt) und Modul 4 anspringen

Klingt eher einfach.
1
if (tastendruck) {
2
  modul++;
3
  if (modul == 2 && jumper2 != gesteckt) modul++;
4
  if (modul == 3 && jumper3 != gesteckt) modul++;
5
  if (modul == 5) modul=0; 
6
}

von xfr (Gast)


Lesenswert?

Peter C. schrieb:
> Hallo,
> ich kann dem Codeing schon folgen....das ist nicht mein Problem sondern
> wenn ich eben in der Modulfolge z.B. 2 und 3 nicht gejumpert habe dann
> sol er einfach weiter springen bis der nächste gesetzte Jumper kommt
> oder es eben wieder bei "0" von vorn weiter geht.

Habe ich Dir doch genau so hingeschrieben. Wenn das "if (JUMPER_SET(2))" 
nicht zutrifft, wird nicht mit break rausgesprungen und der nächste 
Fall wird überprüft.

von Peter C. (Gast)


Lesenswert?

Sorry xfr
endgegen besserem Wissen dachte ich immer nur eine case wird angewählt 
und dann wird heraus gesprungen. Ich wuste nicht das in der Prüfung der 
case die Vergleichvariable geändert werden kann und man so von 2 auf 3 
usw. springen kann.

werde ich gleich mal testen.

Peter

von xfr (Gast)


Lesenswert?

Peter C. schrieb:
> Ich wuste nicht das in der Prüfung der
> case die Vergleichvariable geändert werden kann und man so von 2 auf 3
> usw. springen kann.

So funktionierts auch nicht. Mit der Anweisung "switch" wird einmalig 
zum entsprechenden "case"-Marker gesprungen. Danach läuft das Programm 
einfach von oben nach unten durch, bis ein "break" kommt. Eventuelle 
weitere "case"-Marker interessieren dann nicht mehr, die haben keine 
Bedeutung. Wenn also vor einem "case" kein "break" steht, dann wird 
einfach weitergemacht.

von Peter C. (Gast)


Lesenswert?

Hallo xfr,
so jetzt habe ichs.
Ich habe in den betreffenden case zweig die Abfrage Bedingung eingefügt 
und nur wenn die Bedingung wahr ist wird mit break die case verlassen. 
Ist die Bedingung falsch einfach im else zweig der Abfrage Modul++ 
eingefügt und in der nach folgenden case wir erneut ausgewertet - eben 
wie du schon schreibst das break kommt.
Funktioniert wunderbar, jetzt kann ich die Jumper setzen wie ich mag und 
bei nächsten Tastendruck wird der schon berücksichtigt sofern er an der 
Rheihe ist.
klasse......danke für die für mich schwere Initialzündung.

Gruß
Peter

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.