Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

Re: menudemo.c2 Kategorie: Programmierung (von Markus - 9.06.2009 13:49)
Als Antwort auf menudemo.c2 von Bloodynooby - 8.06.2009 20:42
Ich nutze:
C-Control II Station, OSOPT V3.1
Hallo Bloodynooby
So ganz blutiger Anfänger bist du nun nicht mehr, da du ja bereits ein Programm zum laufen
gebracht hast. Mir ging es ebenso und einige Aaaaahaaaa-Momente waren nötig, bis ich genügend
wusste, um mir beim nächsten Problem die Zähne auszubeissen.
Aus deinen Fragen entnehme ich, dass viele deiner derzeitigen Fragen im Grunde genommen
mit der Problematik bzw. mit der Funktion des Multithreadings zusammenhängen.
Mir scheint, dass du dir zuerst verinnerlichen musst, wie genau das Threading mit den Ressourcen
umgeht, bevor du dich mit den üblichen Programmierproblemen und Fehlern auseinandersetzen kannst.
Das von dir gewählte �bungsmuster scheint mir nicht optimal für den Aufbau des KnowHows.

Wenn du Threading einmal verstanden hast, wirst du sagen, dass es nicht kompliziert ist.
Ich selbst hatte über mehrere Erfahrungsstufen immer wieder gemeint, ich hätte es verstanden.
Nun versuche ich dir möglichst populär das Thema etwas zu erhellen.

Stell dir vor, dein Programm besteht aus z.Bsp. 4 Threads, welche alle die gleiche Priorität haben.
Einer dieser Threads muss bekannterweise den Namen main haben. In diesem werden üblicherweise
die anderen Threads gestartet.
Die CPU beginnt nun mit den ersten Programmzeilen im Thread 1 unterbricht  diese Bearbeitung dann
und beginnt mit der Abarbeitung der ersten Zeilen im Thread 2. Auch hier wird nach wenigen Codezeilen
unterbrochen um mit Thread 3 zu beginnen. Irgend wann werden also alle Zeilen aller Threads
abgearbeitet sein. Bis dahin ist ja alles OK. Nun ist wichtig zu wissen, dass der Thread nicht dann
unterbrochen wird, wenn eine Codezeile bearbeitet wurde, Da der Code in Machienbefehle compiliert
wurde, wird die Codezeile mitten in der Ausführung unterbrochen um in einem anderen Thread
mit einer ebenfalls unterbrochenen Codezeile weiterzufahren.
Das kann z.Bsp. beim Schreiben von Zeilen auf den Display den Anschein machen, dass die Ausgabe
manchmal ruckelartig erfolgt.
Hieraus wird klar, warum man Resourcen nur aus einem einzigen Thread ansprechen sollte, da sonst
z.Bsp. mehrere Threads eine Ausgabe auf den Display ausgeben und sich diese gegenseitig
überschreiben. Auch das Abfragen einer Taste kann somit unterbrochen werden.

Nun zur Frage des Capture:
Wenn man erreichen will, dass in einem Thread eine bestimmte Anzahl Codezeilen an einem Stück,
das heist ohne Unterbruch und weitere Codeverarbeitung in anderen Threads abgearbeitet werden, dann
ist dieser Codeteil mit einem Capturekonstrukt einzurahmen. Somit wird dieser Codeabschnitt immer an
einem Stück abgearbeitet.

Im von dir verwendeten Code kommt dieses Capture in einem Abschnitt vor, in dem auch für mich in
unverständlicher Weise mit den Befehlen reset, resume und yield umgegangen wird.
Yield gibt die Ausführung sofort an den nächsten Thread ab, obschon sich der aktuelle Thread in einer
Capturephase befindet. Zudem ruft er einen anderen Thread auf. Das ganze scheint mir echt Hohe
Schule oder zweifelhaft zu sein.
Versuche es vielleicht mit einem andern Muster z.Bsp. dialog von dieser Webseite.

Gruss: Markus



>
> Hallo,
> nachdem ich Anfang 2009 meine â??neueâ?? CC2 als blutiger Anfänger zum laufen gebracht habe und u.a.
> sogar schon ein eigenständiges Programm zur Nutzung der LED´s als Grenzwertanzeige des DS1631
> (Temperaturfühlers) geschrieben habe, bin ich wie so einige in diesem Forum u.a. auf das Problem
> Multitasking und Zugriff auf das LCD-Display gestoÃ?en. Nachdem die Euphorie also so langsam
> umgeschlagen war habe ich das Teil erstmal gefrustet in einer Ecke verschwinden lassen .
>
> Nun ist aber wieder ein Sonnenstrahl darauf gefallen. AuÃ?erdem  will ich das Teil wenigstens in der
> Garantiezeit noch zerstören^^.
> Da ich niemanden der sich mit Programmierung auskennt kenne, kostet mich dieses neue Hobby
> mehr Zeit und nerven als mir lieb ist. Aber ich hab mir da was in den Kopf gesetzt und dauert es
> 30 Jahre.                                          (wirdâ??s wohl auch :P)
>
> Um einen Ansatzpunkt zu haben, dachte ich an ein Menuemodul, welches Auch den Zugriff auf das
> LCD verwaltet. Nach langer suche habe ich das menudemo.c2 von  Bernd Schmidt (25.10.2002)
> (ganz schön alt!) nach 24h zum laufen gebracht, aber nach 4 Tagen noch nicht ganz verstanden.
>
> Also hier endlich meine Fragen:
>
> 1.String dpy; wofür ? Wird nirgens verwendet oder? (ohne läuft das Programm beim verlassen des
>    Menüs in den Autodisplaymodus nicht mehr.) Wieso?
> 2.Wofür ist initmenu deklariert? Ist nach einmaligem Menueaufruf =1 und dann? Versteh ich nicht.
> 3.Was passiert beim capture flag; genau? Der Stack wird für andere Zugriffe gesperrt. Und mit einem
>    Wert versehen!? Nur in dem Thread oder im ganzen Modul ? Und welcher Wert von welcher variablen?
>    Bedienungsanleitung S77 hab ich nicht verstanden.
> 4.Gerne würde ich an der Stelle irgendeine Taste drücken (stkey.getkey(255))
>    "O=weiter >=enter" im Display ausgeben, da das Autodisplay nur einfriert wenn man nicht gerade
>     O gedrückt hat.
> 5.Wenn man O drückt, springt das Display beim ersten mal wieder in den Autodisplaymodus. Auch
>    das würde ich gerne beheben.
> 6.würde auch gerne  mit C aus jeder Stelle im Thread menu ins Autodisplay gelangen. Bisher ohne
>    Erfolg.. > else if (key==13) {goto_depth = display_menu (0,MENU_DEPTH00_LEN ); } >
> Neben anderen sind das erstmal die wesentlichen Punkte.
>
> Es wäre furchtbar nett, wenn mir jemand mit Kommentaren im thread menu helfen würde!
>
> Wo ich erst drüber Nachdenken möchte wenn ich das Programm verstehe ist ob ein Array für die
> Funktion (Rückgabe wert goto_depth) der Ã?bersicht halber sinnvoll währe  und möglich ist...
> Ich wei� auch noch nicht ob das Menü für meine Anwendung geeignet sein wird. Wahr nur ein Versuch
> sich mit der Materie wieder auseinander zu setzen. Ich möchte natürlich auch Threads aus dem Menü
> starten wollen. Ist mir aber noch nicht einwandfrei gelungen. Wie auch wenn ich das Menü nicht
> 100%ig verstehe         ; _-(
> Vielleicht hat auch jemand ein anderes (kompfortableres) Menü für die Station geschrieben das er mir
> zur Verfügung stellen will.
>
> Da ich schon ein wenig  geändert habe, hab ich alles noch einmal kopiert.
> Ja, zum x ten mal in diesem Forum. Verzeiht mir!
>
>
> /*
>
>   menudemo.c2
>
> BESCHREIBUNG
>   Menusteuerung fuer externes 2-Zeilen Display mit 3 Threads.
>
>   Zur Laufzeit wird ein automatisches Display ausgegeben.
>
>   Wird die (0) Taste gedrueckt, so wird das Autodisplay gestoppt und man kommt in
>   einen Menumodus. Man kann beliebig viele Untermenus (z.B. ueber Konstanten er-
>   zeugen.
>
>   Durch Druecken der (0) Taste kann man ein Menu durchblaettern (einfach ver-
>   zeigert).
>   Durch Druecken der ('->) Taste erreicht man (falls definiert) das Untermenu des
>   Menupunktes, in dem man sich befindet.
>   Durch Druecken der ('->) Taste im letzten Menupunkt eines Menus kommt man wieder
>   in das darueberliegende Menu.
>   Durch Druecken der ('->) Taste im letzten Menupunkt des Menus 0 faengt der
>   Thread Autodisplay wieder an zu laufen ...
>
> //goto_depth999 = reset and start Autodisplay
>
> AUTOR der URSPRUNGSDATEI
>   Bernd Schmidt (25.10.2002)
>
> *******************************************************************************/
>
>
> byte flag;  // Semaphore: Gueltig fuer alle Prozesse
>
> const MENU_DEPTH00_LEN = 7;    // Anzahl der Menue 0 punkte -letzter =zurück oder verlassen
> const MENU_DEPTH01_LEN = 3;
> const MENU_DEPTH02_LEN = 3;
> const MENU_DEPTH03_LEN = 3;
>
> const SPACE5="     ";
> const Menu="Menu ";
> const Punkt="Punkt ";
> int pos;              // Globale Variable fuer Menuposition !!!
> int initmenu;         // Wird 1, wenn Menu durch Benutzer aktiviert
> int dpyam;           // Semaphore: Autodisplay wird dargestellt ?
> string s;
>
> function display_menu (int depth, byte resetpos) returns int  // besser mit Array lösen?
> {
>   int goto_depth;
>   dpyam = 0;
>   if (resetpos!=0) pos = 0;
>   lcdext.home();//Foth warum home?
>   if (depth==0)        // Menu oben
>   {
>     pos=pos+1; if (pos > MENU_DEPTH00_LEN) pos = 1;
>     if      (pos==1)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "1" + SPACE5;
>       lcdext.print(s); goto_depth = 1; }
>     else if (pos==2)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "2" + SPACE5;
>       lcdext.print(s); goto_depth = 2; }
>     else if (pos==3)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "3" + SPACE5;
>       lcdext.print(s); goto_depth = 3; }
>     else if (pos==4)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "4" + SPACE5;
>       lcdext.print(s); goto_depth = 4; }
>     else if (pos==5)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "5" + SPACE5;
>       lcdext.print(s); goto_depth = 5; }
>     else if (pos==6)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "6" + SPACE5;
>       lcdext.print(s); goto_depth = 6; }
>     else if (pos==7)
>     { s=SPACE5 + Menu + "0" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s="   verlassen    ";
>       lcdext.print(s); goto_depth = 999; }
>     sleep 120;
>   }
>   else if (depth==1)                     // Menu 0 / Punkt 1 (0 druecken)-> Menu 1 / Punkt 1
>     { pos=pos+1;
>     if (pos > MENU_DEPTH01_LEN) {pos = 1;}
>     if      (pos==1)
>     { s=SPACE5 + Menu + "1" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "1" + SPACE5;
>       lcdext.print(s); goto_depth = 11; }
>     else if (pos==2)
>     { s=SPACE5 + Menu + "1" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s=SPACE5 + Punkt + "2" + SPACE5;
>       lcdext.print(s); goto_depth = 12; }
>     else if (pos==3)
>     { s=SPACE5 + Menu + "1" + SPACE5;
>       lcdext.print(s); lcdext.line(2);
>       s="    zurueck     ";
>       lcdext.print(s); goto_depth = 0; }
>     sleep 120;
>   }
>   else if (depth==2) {}
>   else if (depth==3) {} // ...
>
>   return goto_depth;    
> }
>
>
>
>
>
> thread autodisplay    //nach belieben ändern
> {
>   lcdext.clear();
>   s="  Autodisplay ";  //ändern  zB.: Menü? Drücke c!
>   lcdext.print(s); lcdext.line(2);
>   s=SPACE5 + Punkt + "1" + SPACE5;  //""
>   lcdext.print(s);
>   sleep 2500;
>   lcdext.clear();
>   s="  Autodisplay ";   //ändern   zB.: Funktionen der F Tasten (evtl Notaus verhalten bei Störungen
>   lcdext.print(s); lcdext.line(2);
>   s=SPACE5 + Punkt + "2" + SPACE5;  //""
>   lcdext.print(s);
>   sleep 2500;
>   lcdext.clear();
>   s="  Autodisplay ";   //ändern   zB.:  Störungsanzeige oder Betriebszustände
>   lcdext.print(s); lcdext.line(2);
>   s=SPACE5 + Punkt + "3" + SPACE5;   //""
>   lcdext.print(s);
>   sleep 2500;
>
>   // ... erweiterbar für weitere Laufanzeige
>  }
>
> thread menu
> {
>   string dpy;  //wofür? dpy kommt nicht vor. ohne: Autodisplay Punkt 1 anzeige Absturz
>   int key;
>   int depth;
>   int goto_depth;
>   key = stkeyb.get();
>   if (key != 255)  // Taste wurde gedrueckt
>   {plm.beep(plm.TONE_E1);sleep 10;    //Tastenton test
>     plm.beep(plm.TONE_OFF);           //Tastentontest ende
>     dpyam = 0;
>     halt autodisplay;
>     capture flag;                                                    /*wertzuweisung flag 1...255 wenn
>                                                                            flag =0, blockiert fremde zugriffe(S.77) /Notaus
>                                                                            jetzt noch möglich?*/
>     if (key==0)                                                       // [0] : Menu blaettern
>     {
>      goto_depth = display_menu(depth, 0);
>     }
>     else if (key==14)                          // ändern:(Entprellzeiten? gegen fehleingabe!)   ['->] : Menu Enter
>     {
>       depth = goto_depth;
>      
>       if (depth==999)
>       {
>         dpyam = 1;
>         sleep 200; lcdext.clear();
>         pos = 0; depth = 0;
>         reset autodisplay;
>         resume autodisplay;
>         reset;
>         yield;
>       }
>       else if (initmenu==0)
>       {
>         goto_depth = display_menu(depth, 0);
>         initmenu = 1;
>       }
>       else goto_depth = display_menu(depth, 1);
>     }
>     release;  //blockade flag wird aufgehoben
>   }
> }
>
>
>
> thread main
>
> {
>   stports.init();
>   lcdext.init();
>   lcdext.clear();
>   sleep(2000);
>   s=" Menudemo 1.0 ";                                     //ändern in zB"Herzlich"
>   lcdext.print(s);
>   lcdext.line(2);
>   s="0=weiter >=enter";                                   //ändern in zB "Wilkommen"
>   lcdext.print(s);
>   sleep 2000;
>   dpyam = 1;
>
>   loop
>   {
>     if (dpyam==1) { run autodisplay; }
>     run menu;
>   }
> }


    Antwort schreiben


Antworten:

Re: menudemo.c2 (von nitraM - 9.06.2009 14:55)
    Re: menudemo.c2 (von Bloodynooby - 13.06.2009 18:26)