Forum: Compiler & IDEs LCD-Menü Pointerfrage


von Marcus M (Gast)


Lesenswert?

Hallo Leute,

nachdem ich die Thread:

    http://www.mikrocontroller.net/forum/read-2-40721.html#40721
    http://www.mikrocontroller.net/forum/read-2-18413.html#18413

und

    http://www.mikrocontroller.net/forum/read-2-78266.html

gelesen habe, hab ich noch eine kleine Frage.
Wenn ich mein Menü mit
static const char menu0[] PROGMEM = "Hauptmenu";
static const char menu1[] PROGMEN = "zweites Menü";

im Flash abgelegt habe, wie bekomme ich dann die folgenden Pointer?
Das sind doch IMHO dann funktion - Pointer und keine Datapointer.

typedef struct{

  const char *name; //This one!
  const menustruktur* next; // This one
  const menustruktur* previous; //This one
  const menustruktur* sub; //This one
  const menustruktur* up;  // This one
  void ( *funktion )( void );
}menustruktur;

menustruktur Menu[240];

Somit könnte ich direkt mit einer Funktion z.B.


void do_Next(menustruktur entrie){

  if (TASTER_NEXT) {
    if (entrie.next != 0x0) { //sonst wird die Funktion ausgeführt
      LCD_Write((entrie.next).name);
      return (entrie.next);
    }
    else {
     entrie.funktion();
     return (entrie.this());
    }
  }
  else
   if (entrie.prev != 0x0) {
      LCD_Write((entrie.prev).name);
      return (entrie.prev);
   }
   else {
      entrie.funktion();
      return (entrie.this());
   }
  }

}

die Sache auf das Display zaubern und dann auch die passende Funktion
ausführen.

in Main würde das dann so aussehen:

int main (void) {


// do something
menustruktur temp_ent = Menu[0];

temp_ent = do_Next(temp_ent);

}

Ich hoffe, jedem ist jetzt klar, was ich da vor habe.
Ich kenne mich so halbwegs mit Pointern aus und glaube das auch
verstanden zu haben. Wenn da jetzt irgendwelche groben Fehler drin
sind, sagt mir das bitte.

Geht das so überhaupt?

Gruß Marcus

PS: Sorry, das diese Frage versehendlich in die Codesammlung gekommen
ist!

von Stefan Kleinwort (Gast)


Lesenswert?

Hi Marcus,

Deine typedef muss schonmal anders aussehen, damit die
Selbst-Referenzierung funktioniert. Das const gehört nicht in die
typedef, sondern in die Variablen-Deklaration, mit PROG_MEM:

typedef struct def_menustruktur{
  struct def_menustruktur* next;
  struct def_menustruktur* previous;
  struct def_menustruktur* sub;
  struct def_menustruktur* up;
  void ( *funktion )( void );
}menustruktur;


void do_anything(void);
void do_everything(void);
void do_nothing(void);


PROGMEM menustruktur menu[3] =
{
  { &menu[1], &menu[2], &menu[0], &menu[0], do_anything},
  { &menu[2], &menu[0], &menu[1], &menu[1], do_everything},
  { &menu[0], &menu[1], &menu[2], &menu[2], do_nothing}
};


void do_anything(void){
}

void do_everything(void){
}

void do_nothing(void){
}


In den Bearbeitungsroutinen musst Du bei JEDEM Zugriff auf die
Struktur-Daten pgm_read_word bzw. pgm_read_byte verwenden, hier mal
Deine Function etwas gekürzt:


int do_Next(menustruktur entrie){
  void (*my_func_ptr)(void);

  if (TASTER_NEXT) {
    if (pgm_read_word(entrie.next) != 0x0) { //sonst wird die Funktion
ausgeführt
      return (pgm_read_word(entrie.next));
    }
    else {
     my_func_ptr = (void*) pgm_read_word(entrie.funktion);
     my_func_ptr();
     return (pgm_read_word(entrie.sub));
    }
  }
}


gcc übersatzt das Ganze so fehlerfrei, ob der Aufruf der Funktion so
richtig klappt, habe ich jetzt mal nicht praktisch ausprobiert.

Die Art das Menu zu programmieren, ist richtig. Mit den Pointern auf
Funktionen kann man richtig klasse Sachen machen. Du kannst übrigens
den Funktionen auch Werte mitgeben ...

Viel Spass, Stefan

von Marcus M (Gast)


Lesenswert?

Hallo Stefan,

langsam raff ich, warum ich mich immer nur im Kreis gedreht habe -
leider! Ich bin zwar viel "Pointern" gewohnt, denn bei so richtig
großen Arrays (> 200MB) wid die ganze Sache richtig spassig ;-).
Leider bin ich bisher immer x86er gewöhnt und der nahm einen diesen
Kram ab. Ich fand bisher nur nicht heraus, wann und wie ich die Pointer
auf das Flash bekomme.

THX, werd mal mein Glück versuchen.

Danke

Gruß Marcus

von Marcus M (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

leider komme ich mit dem speichern im Flash nicht ganz weiter.
Egal wie ich es wende, entweder läuft der Code und das Display zeigt
ausschnitte aus dem Programm oder der Mega16 dreht vor lauter resetten
durch ;-).

Wär jemand mal so lieb und würde auf den C - Code einen kleinen Blick
werfen?

ich raff nicht, wo der Fehler liegt!

Danke!

Gruß Marcus

von Stefan Kleinwort (Gast)


Lesenswert?

void menu (void) {

  menustruktur my_struct;
  char temp[16];
  strcpy_P(temp, (char*)pgm_read_word(Hauptmenu.name));
  for (int i = 0; i < 4; i++) {
    LCD_write(i, temp);
    my_struct = pgm_read_word(my_struct.down);
                ^                         ^
                I                         I
                I                         my_struct scheint im 1.
                I                         Durchlauf nicht
                I                          initialisiert zu sein
                I
                deshalb wird my_struct
                hier mit Schrott beschrieben

    strcpy_P(temp, (char*)pgm_read_word(my_struct.name));
                                                    ^
                                                    I
                                                    Und hier ist dann
                                                    leider auch Müll
                                                    drin

Stefan

von mthomas (Gast)


Lesenswert?

nur als "Einwurf" (und weil das Ding mein "Steckepferd" ist/war): Im
Quellcode der vorinstallierten Anwendung des AVR-Butterfly findet sich
einiges an nutzlichen Informationen zu Menustrukturen, Initialsierung
und Pointern. Das avr-gcc-spezifische (progmem) kann man sich im
gcc-port anschauen. ("Eigenwerbung":)
www.siwawi.arubi.uni-kl.de/avr_projects

von Marcus M (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Stefan,

das Problem habe ich mitlerweile gelöst.
Mein Problem scheint aber ganz wo anders zu liegen.

Schau Dir mal "Version 2" an.

Meine ganz dumme Frage ist folgende:
Wenn ich den z.B. (my_structur -> up) -> name bekommmen will, muß ich
doch folgendes tun:

1. Adresse von my_struct herausbekommen
2. Addresse von my_struct -> up herausbekommen mit:
     pgm_read_word(my_struct -> up)
3. Inhalt von my_struct -> up lesen mit:
     pgm_read_byte(pgm_read_word(my_struct-> up));
4. Danach irgendwie my_struct diesen Wert zuweisen:
     my_struct = pgm_read_byte(pgm_read_word(my_struct -> up);
5. Nun die Addresse von my_struct -> name herausbekommen mit:
     pgm_read_word(my_struct->name);
7. diesen Inhalt einer temporären Variablen zuweisen mit:
     char temp[16];
     strcpy_P (temp, pgm_read_word(my_struct->name);

Irgendwo hier liegt mein Fehler.
Ich hoffe, jemand von Euch kann mir den Denkfehler mal kurz erklären
und mir vom Schlauch helfen. Danke

Gruß Marcus

von Stefan Kleinwort (Gast)


Lesenswert?

Hi Marcus,

ich arbeite gerade in meinem eigenen Projekt mit dem Flash und da ist
mir nachträglich eingefallen, dass bei Dir fast überall die
Adress-Operatoren "&" fehlen:

my_struct = pgm_read_word(&(my_struct.down));
                          ^
                          I
                           hier z.B. fehlt er

pgm_read_word und pgm_read_byte sind ja Makros und liefern deshalb
leider keinen Fehler, wenn man sie mit den falschen Typen benutzt.

Stefan

von Marcus M (Gast)


Lesenswert?

Hallo Stefan,

Danke, ich hab Deinen Beitrag erst heute gelesen, weil ich derzeit
Fliegertage habe - Segelflug ;-)

Ich dachte immer, das Makro würde von sich aus die Adresse auflösen.
Aber egal, werd mal mein Glück probeiren. THX!!

Gruß Marcus

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.