Forum: Mikrocontroller und Digitale Elektronik Menü im Programmspeicher anlegen


von Ben (Gast)


Lesenswert?

Hallo,

ich möchte ein Menü im Programmspeicher anlegen, damit es nicht den 
Arbeitsspeicher belastet. Für einen Menüeintrag habe ich einen struct 
erstellt, welcher Verweise auf den vorherigen, nächsten, ... 
Menüeintrag, so wie einen Text enthält. Des Weiteren beinhaltet er vier 
Verweise auf Funktionen, die später beim Druck von vier verschiedenen 
Tasten zum Navigieren und Ausführen von Funktionen dienen sollen.

Ich habe jedoch das Problem, dass beim Anlegen von z.B. Menüeintrag 0, 
Menüeintrag 1 noch nicht vorhanden ist, Menüeintrag 0 aber auf 
Menüeintrag 1 verweisen. Soll dies für zwangläufig zu einem Fehler.

Eine Alternative wäre, dass ich das Menü in den Arbeitsspeicher packen 
und die Verweise erst in einer Initialiserung anlege, aber ich wollten 
Arbeitsspeicher eigentlich nicht belasten.

Hat jemand eine Idee, wie ich dieses Problem lösen kann?

Des Weiteren tritt noch ein Fehler auf, den ich gerade nicht lösen kann 
(stehe auf dem Schlauch): "warning: initialization discards qualifiers 
from pointer target type" Der Fehler tritt in den Zeilen auf, in denen 
ich einen entsprechenden Kommentar eingefügt habe. (Beim Verweis auf 
andere Einträge.)

Gruß
Ben
1
typedef struct MENU{
2
  struct MENU *prev,       //vorheriger Menüpunkt
3
  *next,                   //nächster Menüpunkt
4
  *upmen,                  //übergeordneter Menüpunkt
5
  *downmen;                //untergeordneter Menüpunkt
6
  const int8_t *mtext;     //Menütext
7
  void ( *f0 ) (int8_t i), //Tasterfunktionen 1
8
  ( *f1 ) (int8_t i),      //Tasterfunktionen 1
9
  ( *f2 ) (int8_t i),      //Tasterfunktionen 1
10
  ( *f3 ) (int8_t i);      //Tasterfunktionen 1
11
} MENU_ENTRY;
12
13
14
void test0(int8_t i);
15
void test1(int8_t i);
16
void test2(int8_t i);
17
void test3(int8_t i);
18
19
20
MENU_ENTRY *menu_root;
21
22
//Menü-Struktur (Beispiel)
23
//
24
// |-Menü0
25
// | |-Menü00
26
// |-Menü1
27
// |-Menü2
28
29
const int8_t menu0_text[] PROGMEM = "Menue0\0";
30
const int8_t menu00_text[] PROGMEM = "Menue00\0";
31
const int8_t menu1_text[] PROGMEM = "Menue1\0";
32
const int8_t menu2_text[] PROGMEM = "Menue2\0";
33
34
const MENU_ENTRY menu0 PROGMEM = {
35
  NULL, 
36
  &menu1, 
37
  NULL, 
38
  &menu00, //hier tritt Fehler auf
39
  menu0_text, 
40
  test0, 
41
  test1, 
42
  test2,   
43
  test3};
44
45
const MENU_ENTRY menu00 PROGMEM = {
46
  NULL, 
47
  NULL, 
48
  &menu0, 
49
  NULL, 
50
  menu00_text, 
51
  test0, 
52
  test1, 
53
  test2, 
54
  test3};
55
56
const MENU_ENTRY menu1 PROGMEM = {
57
  &menu0,  //hier tritt Fehler auf
58
  &menu2, 
59
  NULL, 
60
  NULL, 
61
  menu1_text, 
62
  test0, 
63
  test1, 
64
  test2, 
65
  test3};
66
67
const MENU_ENTRY menu2 PROGMEM = {
68
  &menu1,  //hier tritt Fehler auf
69
  NULL, 
70
  NULL, 
71
  NULL, 
72
  menu2_text, 
73
  test0, 
74
  test1, 
75
  test2, 
76
  test3};
77
78
79
void test0(int8_t i)
80
{
81
  //...
82
}
83
84
void test1(int8_t i)
85
{
86
  //...
87
}
88
89
void test2(int8_t i)
90
{
91
  //...
92
}
93
94
void test3(int8_t i)
95
{
96
  //...
97
}

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>Ich habe jedoch das Problem, dass beim Anlegen von z.B. Menüeintrag 0,
>Menüeintrag 1 noch nicht vorhanden ist, Menüeintrag 0 aber auf
>Menüeintrag 1 verweisen. Soll dies für zwangläufig zu einem Fehler.

Das löst man mit Prototypen:

extern const MENU_ENTRY menu0 PROGMEM;
extern const MENU_ENTRY menu00 PROGMEM;

usw.
ganz am Anfang deklarieren.

Den anderen Fehler kann ich im Moment nicht nachvollziehen, weil er 
nicht bei allen Einträgen auftritt.

Grüße,

Peter

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Ich würde mal folgendes probieren:

typedef struct MENU{
  struct MENU PROGMEM *prev,
usw.

Grüße,

Peter

von Stefan E. (sternst)


Lesenswert?

Was den zweiten Fehler betrifft:
Da fehlt ein const bei den Zeigern in der struct-Definition.

von Ben (Gast)


Lesenswert?

Super, danke. Jetzt sind die Fehler behoben, in dem ich Prototypen 
angelegt habe und const bei den Zeigern in der struct-Def. verwende.

Jetzt tritt jedoch bei der Zuweisung des Pointers auf das Menü
1
menu_root = &menu0;
eine Warnung auf: "assignment discards qualifiers from pointer target 
type".
Diese kann ich beheben, wenn ich "menu_root" als const deklariere. Aber 
dies wäre ja nicht so sinnvoll, da ich den Zeiger ja umbiegen möchte.

Hab ihr eine Idee?

Gruß
Ben

von Stefan E. (sternst)


Lesenswert?

Ben schrieb:
> Diese kann ich beheben, wenn ich "menu_root" als const deklariere. Aber
> dies wäre ja nicht so sinnvoll, da ich den Zeiger ja umbiegen möchte.

Und? Es ist ein Unterschied, ob der Zeiger selbst const ist, oder das, 
worauf er zeigt.

von Ben (Gast)


Lesenswert?

Das ist mir schon klar. Da ich jedoch nicht weiß, woher die 
Fehlermeldung kommt, habe ich dies mal ausprobiert. Aber mir ist klar, 
dass das "falsch" ist. Es hat mich nur gewundert, dass dann die 
Fehlermeldung weg ist.

Hat noch jemand einen Lösungsvorschlag?

von Karl H. (kbuchegg)


Lesenswert?

Ben schrieb:

>
> Hat noch jemand einen Lösungsvorschlag?

> Das ist mir schon klar.


Wenn dir das schon klar ist, wo liegt dann das Problem?


const int * pPtr;

  pPtr ist ein Pointer auf einen int. Und dieser int ist const, kann
  also nicht über den Pointer verändert werden. Der Pointer aber, der
  ist nicht const, du kannst pPtr jederzeit einen neuen Wert zuweisen

  const int i = 5;
  const int j = 8;
  const int* pPtr;

  pPtr = &i;    // legal
  pPtr = &j;    // legal
  *pPtr = 9;    // illegal, denn pPtr zeigt ja auf etwas das const ist


Im Gegensatz dazu:

int * const pPtr;

  Jetzt ist das ebenfalls ein Pointer, der auf einen int zeigt. Aber
  diesmal kann der int über den Pointer verändert werden. Der int ist
  nicht const. Wohl aber ist es die Pointervariable, die kann nicht
  auf einen anderen int gesetzt werden.

  int i = 5;
  int j = 8;
  int* const pPtr = &i;

  pPtr = &j;    // illegal, denn pPtr selber ist const
  *pPtr = 9;    // völlig legal, das const bezieht sich auf pPtr und
                // nicht darauf worauf es zeigt

Und dann gibt es noch

const int * const pPtr;

  Wieder ein Pointer, der auf einen int zeigt. Aber diesmal ist sowohl
  der int, als auch die Pointervariable const. Keines von beiden kann
  verändert werden.

  const int i = 5;
  const int j = 8;
  const int* const pPtr = &i;

  pPtr = &j;    // illegal
  *pPtr = 9;    // illegal


> Diese kann ich beheben, wenn ich "menu_root" als const deklariere. Aber
> dies wäre ja nicht so sinnvoll, da ich den Zeiger ja umbiegen möchte.

Was hindert dich am umbiegen?

von Martin (Gast)


Lesenswert?

Peter Diener schrieb:
> Das löst man mit Prototypen:

Nein, mit forward declarations.

Prototypen gibts bei Funktionen.

(Deine Lösung war richtig, nur die Begrifflichkeiten sollte man sauber 
benutzen)

von Ben (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> const int * pPtr;
>
> int * const pPtr;
>
> const int * const pPtr;

Ok, dann ich es doch nicht richtig verstanden. Vielen Dank für deine 
ausführliche Erklärung. Jetzt ist mir das klar.

Gruß
Ben

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.