Forum: Mikrocontroller und Digitale Elektronik Menüs mit Funktionszeigern


von CJ (Gast)


Lesenswert?

Hallo zusammen.
Ich versuche zur Zeit ein ordentliches Menü für mein GLCD zu 
programmieren.
Ich habe einfach nur mal bei mikrocontroller.net gesucht und auch 
einiges gefunden.
siehe: http://www.mikrocontroller.net/articles/Funktionszeiger_in_C

Unter der Überschrift (Menüs mit Funktionszeigern)
steht:
struct MenuEntry MainMenu[] =
{
   // Der Funktion HandleEdit soll beim Aufruf 23 mitgegeben werden
   { "Edit",  HandleEdit,  23 },
   { "Copy",  HandleCopy,   0 },
   { "Paste", HandlePaste,  0 }
};

diesen Teil versteh ich überhaupt nicht. Kann mir den einer erklären.? 
Bzw. auch sagen, wie ich das schreiben soll, für mein GLCD.? Da der code 
ja nur für eine Konsole ist.


Danke schonmal
MfG

von Marcel (Gast)


Lesenswert?

Ist im Grunde recht einfach.

CJ schrieb:
> { "Edit",  HandleEdit,  23 },

"Edit" ist der Text, der auf dem Display steht. "HandleEdit" ist die 
Funktion, die aufgerufen werden soll und 23 der Parameter. Wenn der 
Benutzer die Bestätigen-Taste drückt musst du dafür sorgen, dass
1
HandleEdit(23);
aufgerufen wird.

Wie das ganze mit deinem GLCD geht weisst nur du, da es viele 
verschiedene GLCD gibt. Es gibt für die gebräuchlisten fertige 
Libraries, wobei selber schreiben immer lehrreicher ist.
Ansonsten wird mit Taste Hoch/Runter der Menüeintrag ausgewählt und mit 
Bestätigen die zugeordnete Funktion aufgerufen.

von CJ (Gast)


Lesenswert?

Marcel schrieb:
> "Edit" ist der Text, der auf dem Display steht. "HandleEdit" ist die
> Funktion, die aufgerufen werden soll und 23 der Parameter. Wenn der
> Benutzer die Bestätigen-Taste drückt musst du dafür sorgen,
> dassHandleEdit(23);
> aufgerufen wird.

alles klar. ist ja doch recht einfach. vielen dank

von Marian (phiarc) Benutzerseite


Angehängte Dateien:

Lesenswert?

Einfaches async Menüsystem in Anhang, da kannst du dir das aus einer 
Produktiv-Umbegung zu Gemüte führen ;)

von CJ (Gast)


Lesenswert?

Marian B. schrieb:
> Einfaches async Menüsystem in Anhang, da kannst du dir das aus einer
> Produktiv-Umbegung zu Gemüte führen ;)

super danke.
Hättest du auch ein komplettes Projekt mit diesem Menüsystem.?

von Marian (phiarc) Benutzerseite


Lesenswert?

So spontan nicht, ist aber sehr einfach zu benutzen.

Menustruktur kann man komplett statisch machen:

    menu_entry_t menu_entries[] = {
        {"Charge battery", MENU_TYPE_NORMAL, {{0}}},
        {"Version", MENU_TYPE_CALLBACK, .data.callback = 
{f_show_version, 0}},
    };
    menu_t menu = {
        menu_entries, 2, 0, f_menu_writer, display_clear
    };

f_menu_writer ist dann einfach eine Funktion, die eine Zeile aufm 
Display ausgibt und ggf. markiert (display_flags). display_clear wird 
aufgerufen vorm Ausgeben des Menüs und würde hier z.B. den Displayinhalt 
löschen

Menu aktivieren

    menu_state_init(menu);

Und dann brauchst du nur noch in menu_state_advance die Nutzereingaben 
reinfüttern (deswegen asynchron genannt), bis es mal !0 zurückgibt. Dann 
ist menu->selection entweder -1 für Abbruch oder ( ein Index, ggf. wurde 
ein Callback aufgerufen ).

edit: hab den letzten Satz mal "geklammert" :)

: Bearbeitet durch User
von CJ (Gast)


Lesenswert?

aber wo gebe ich meine texte an, die das glcd anzeigen soll?

von Marian (phiarc) Benutzerseite


Lesenswert?

Die stehen in den menu_entry_t drin (im Beispiel das menu_entries[] 
array), direkt der erste Eintrag.

Wie du das anzeigst ist nicht Sache des menu-Moduls, damit man daran 
nix ändern muss, is das 100 % hardware-unabhängig. Dafür sind die beiden 
Callbacks in menu_t da:
1
/**
2
 * Menu display function
3
 *
4
 * @param line Display line
5
 * @param display_flags @see menu_display_flags
6
 * @param entry menu entry to display
7
 */
8
typedef void (*menu_write_t)(uint8_t line, uint8_t display_flags, const menu_entry_t *entry); 
9
10
/**
11
 * Called right before the first batched calls to menu_write_t
12
 */
13
typedef void (*menu_write_begin_t)(void);
14
15
// ...
16
17
/**
18
 * Struct for a complete menu, containing all necessary data and state.
19
 */
20
typedef struct {
21
    /// Array of entries
22
    menu_entry_t *entries;
23
    /// Number of entries
24
    int num_entries;
25
    /// Selected entry (0-indexed)
26
    int selection;
27
28
    /// Writer function
29
    menu_write_t write;
30
    /// Writer start function
31
    menu_write_begin_t write_begin;
32
} menu_t;

Wenn das Menü dargestellt werden soll, wird zuerst write_begin 
aufgerufen und dann für jeden anzuzeigenden Eintrag write.

: Bearbeitet durch User
von cprog (Gast)


Lesenswert?

Marian B. schrieb:
> Menustruktur kann man komplett statisch machen:
>
>     menu_entry_t menu_entries[] = {
>         {"Charge battery", MENU_TYPE_NORMAL, {{0}}},
>         {"Version", MENU_TYPE_CALLBACK, .data.callback =
> {f_show_version, 0}},
>     };
>     menu_t menu = {
>         menu_entries, 2, 0, f_menu_writer, display_clear
>     };



hallo zusammen.
kann mir jemand diesen abschnitt erklären.?
bzw. was genau soll der eintrag {f_show_version, 0}} bedeuten.?

Marian B. schrieb:
> menu_entries, 2, 0, f_menu_writer, display_clear

wo ist die 2 bzw. die 0 zuzuordnen.? ist sicherlich für die position 
verantwortlich(f_menu_writer)

von Marian (phiarc) Benutzerseite


Lesenswert?

Die Angaben sind in der gleichen Reihenfolge wie in der Definition von 
menu_t
1
/**
2
 * Struct for a complete menu, containing all necessary data and state.
3
 */
4
typedef struct {
5
    /// Array of entries
6
    menu_entry_t *entries;
7
    /// Number of entries
8
    int num_entries;
9
    /// Selected entry (0-indexed)
10
    int selection;
11
12
    /// Writer function
13
    menu_write_t write;
14
    /// Writer start function
15
    menu_write_begin_t write_begin;
16
} menu_t;

i.e. 2 Einträge, 0 = der erste ist ausgewählt

> bzw. was genau soll der eintrag {f_show_version, 0}} bedeuten.?

f_show_version ist der Callback, der aufgerufen wird, wenn der Eintrag 
ausgewählt wird. 0 ist der void*, den der Callback bekommt, i.e. der 
wird hier nicht benutzt und ist einfach dafür da, beliebige Daten 
durchzureichen.
1
/**
2
 * Struct for menu entries
3
 */
4
struct menu_entry_t {
5
    /// Displayed text
6
    const char *text;
7
    /// Entry type
8
    const menu_type type;
9
    /// Entry data valid fields depend on type
10
    union {
11
  /// Data for MENU_TYPE_CALLBACK
12
  struct {
13
      menu_entry_callback_t cb;
14
      void *data;
15
  } callback;
16
    } data;
17
};



Wichtig zu verstehen bei dem Code, den ich oben gepostet habe, ist, dass 
sich der Code weder um die Anzeige von dem Menü kümmert (Ausgabe der 
Einträge ist die Aufgabe von einer menu_write_t-Funktion), noch um die 
Abfrage von Nutzereingaben (dazu ruft man dann menu_state_advance mit 
der entsprechenden Eingabe auf). Auch kann man sehr einfach zusätzliche 
Typen von Einträgen realisieren (dafür ist das union in menu_entry_t da)

: Bearbeitet durch User
von cprog (Gast)


Lesenswert?

und das f_show_version muss ich selber noch deklarieren.?
weil in meinem programm kennts das nicht

von Marian (phiarc) Benutzerseite


Lesenswert?

Ja, was passieren soll, wenn ein Eintrag ausgewählt wird, musst du 
selber programmieren.

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.