mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Menü über RS232 ausgeben


Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich mache mir grad Gedanken, wie ich über RS232 ein Menü darstellen
kann. Ich habe einige C-Beispiele für Displays gefunden, bei denen ein
struct verwendet wurde, bei dem mittels Pointer auf weitere structs
verwiesen wurde.
Die Pointer haben jeweils auf den nächsten bzw. vorhergehenden
Menü-Eintrag gezeigt, oder auf den drüber- bzw. drunterliegenden. Das
heisst, es wurde immer nur ein Eintrag angezeigt. Ich weiss nicht, ob
und wie ich dieses Schema auf mein Menü anwenden kann.

Ich möchte über die serielle Schnittstelle ein Menü ausgeben, welches
mehrere Einträge hat. Die Menü-Struktur sieht in etwa so aus:

HAUPTMENÜ
  MENU_1
    MENU_1
      usw.
    MENU_2
      usw.
    MENU_3
      usw.
  MENU_2
    MENU_1
      usw.
    MENU_2
      usw.
    MENU_3
      usw.
  MENU_3
    MENU_1
      usw.
    MENU_2
      usw.
    MENU_3
      usw.
  usw.

Also hat jedes Menü eine beliebige Anzahl von Untereinträgen, das ganze
in beliebiger Tiefe. Es soll bei Anwahl eines Eintrages entweder ein
zugehöriges Untermenü gezeigt,eine Funktion aufgerufen oder eine Ebene
zurückgesprungen werden.

Ich weiss jetzt nicht, wie ich das realisieren kann. Beim Display-Menü
ist mir der Ablauf klar, es wird ja immer nur ein Eintrag gezeigt.
Aber ich möchte ja quasi mehrere Einträge gleichzeitig darstellen und
anwählen können.

Wer kann helfen?

Ralf

Autor: Danny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe sowas in der Art bei meiner Technikerarbeit mit einem
"intelligenten" Touch-Display gemacht. Das war RS232 und I2C-Fähig
und man konnte Makros im Display hinterlegen die dann vom µC abgerufen
werden könnnen. Da war so ziemlich alles mit machbar, sogar Pull-Down
Menüs. Ich habe damals das EA-Kit 128 verwendet
(http://www.lcd-module.de/deu/pdf/grafik/kit128.pdf).

Autor: Danny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry falsches Display (sollte aber egal sein)...
--> http://www.lcd-module.de/deu/pdf/grafik/kit240-6.pdf

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wuerde das ganze so machen:

Ich mach eine struct die einen Menüeintrag definiert.
Ein Menüeintrag besteht aus einem anzuzeigenden Text sowie
einem Funktionspointer.
Ein komplettes Menue ist dann einfach ein Array aus derartigen
Einträgen.
Die Verwaltungsroutine dazu macht das übliche: Einen Menüeintrag
auswählen und vom ausgewählten Menüeintrag den Funktionspointer
nehmen und die zugehörige Funktion aufrufen. Eine derartige
Funktion kann dann selbst wieder ein Menü aufbauen usw., usw.
Ist der Funktionspointer 0, dann wird die Funktion klarerweise
nicht aufgerufen, sondern die Verwaltungsfunktion return-ed
ganz normal.

Ach was solls.
Ungefähr so (auf einem PC unter DOS programmiert):

#include <stdio.h>

#define ELEMENTS(x)  (sizeof(x)/sizeof(*x))

typedef void (MenuFnct)( void );

struct MenuEntry
{
  char      Text[20];
  MenuFnct* Function;
};

void HandleMenu( const char* MenuTitle, struct MenuEntry* Menu,
unsigned char MenuSize )
{
  int i;
  int Auswahl;

  do {

    printf( "%s\n", MenuTitle );

    for( i = 0; i < MenuSize; ++i )
      printf( "%d: %s\n", i+1, Menu[i].Text );

    do {
      printf( "\nWahl: " );
      scanf( "%d", &Auswahl );
    } while( Auswahl < 1 || Auswahl > MenuSize );

    Auswahl--;

    if( Menu[Auswahl].Function ) {
      (*Menu[Auswahl].Function)();
      printf( "\n" );
    }

  } while( Menu[Auswahl].Function );
}

void HandleNew( void )
{
  printf( "Funktion 'Neu' ausgewählt\n" );
}

void HandleOpen( void )
{
  printf( "Funktion 'Öffnen' ausgewählt\n" );
}

void HandleSave( void )
{
  printf( "Funktion 'Speichern' ausgewählt\n" );
}

void HandleCut( void )
{
  printf( "Funktion 'Ausschneiden' ausgewählt\n" );
}

void HandleCopy( void )
{
  printf( "Funktion 'Kopieren' ausgewählt\n" );
}

void HandlePaste( void )
{
  printf( "Funktion 'Einfügen' ausgewählt\n" );
}

void HandleClose( void )
{
  printf( "Funktion 'Schjließen' ausgewählt\n" );
}

void SelectMenu( void )
{
  struct MenuEntry SelectMenu[] =
    { { "Zurück",    0 } };

  HandleMenu( "Auswählen", SelectMenu, ELEMENTS( SelectMenu ) );
}

void DateiMenu( void )
{
  struct MenuEntry FileMenu[] =
    { { "Neu",       HandleNew },
      { "Öffnen",    HandleOpen },
      { "Speichern", HandleSave },
      { "Zurück",    0 } };

  HandleMenu( "Datei", FileMenu, ELEMENTS( FileMenu ) );
}

void BearbeitenMenu( void )
{
  struct MenuEntry EditMenu[] =
    { { "Ausschneiden", HandleCut },
      { "Kopieren",     HandleCopy },
      { "Einsetzen",    HandlePaste },
      { "Zurück",    0 } };

  HandleMenu( "Bearbeiten", EditMenu, ELEMENTS( EditMenu ) );
}

void AnsichtMenu( void )
{
  struct MenuEntry ViewMenu[] =
    { { "Auswählen",    SelectMenu },
      { "Schließen",    HandleClose },
      { "Zurück",    0 } };

  HandleMenu( "Ansicht", ViewMenu, ELEMENTS( ViewMenu ) );
}

int main()
{
  struct MenuEntry MainMenu[] =
     { { "Datei",       DateiMenu },
       { "Bearbeiten",  BearbeitenMenu },
       { "Ansicht",     AnsichtMenu },
       { "Beenden",     0 } };

  HandleMenu( "Hauptmenue", MainMenu, ELEMENTS( MainMenu ) );
}

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Karl Heinz,

ui, das ist ein ordentliches Stück Code, danke. Ich werd mir das mal zu
Gemüte führen.

Ralf

Autor: MiGu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

dein Code sieht sehr interessant aus. Habe ihn mal nurchgearbeitet und 
versuche ihn gerade auf einen uC zu implementieren. Folgendes habe ich 
vor:

Es soll ein zweizeiliges LCD für die Anzeige verwendet werden. In der 
ersten Zeile steht das aktuelle Menü, z.B. "Hauptmenü". In der zweiten 
Zeile soll das Untermenü stehen.

Für die Bedienung sollan Tasten am uC dienen. Eine entsprechende 
Entprellroutine für "Up", "Down" und "Enter" ist vorhanden, es wird 
jeweils ein FLAG bei Betätigung gesetzt.

Die HandleMenu-Routine soll nicht in einer do-while-Schleife laufen, 
sondern es soll wieder rausgegangen werden, um weitere Aufgaben zu 
erfüllen. Statt dessen soll das jeweilige Menü über Zeiger "gemerkt" 
werden und beim nächsten Durchlauf auf die "Enter-Taste" in das 
Untermenü gesprungen werden. Es kann ja auf dem LCD immer nur ein 
Untermenü angezeigt werden.

So wollte ich deinen Code anpassen - momentan hänge ich gerade in der 
Umsetzung der Zeiger-Problematik.

Hast du eine Idee, wie man das machen könnte? Evtl über Next-Prev-Zeiger 
der MenuEvent-Struktur?

Danke im voraus.
Michael.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Menues macht man am besten mit Statusmaschinen. Jede Aenderung 
(up,down..) andert den Status. Das laeuft dann im mmenuhaendler auf 
einen switch statement hinaus. Gewartet wird im switch nirgends. 
Dargestellt mit einer State-event-acrion matrix.

rene

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Stefan war so nett seinen Code zu posten
Beitrag "LCD - Menu"

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ps.: In diesen Beispiel liegt das Menu nicht Flash des Mikrocontrollers. 
Die Menueintraege sollten lieber im Flash stehen als im RAM.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.