Deine struct-Deklarationen sind falsch. Das typedef hat da nix verloren.
Wenn Du
struct MENU_ENTRY
{
//...
} MENU_t;
schreibst, dann ist MENU_t eine struct vom "Typ" MENU_ENTRY. MENU_t
ist kein Strukturtyp, den Du für weitere Definitionen verwenden kannst,
sondern eine Strukturvariable mit den Eigenschaften der zuvor
deklarierten struct MENU_ENTRY! Also weiter unten z.B.
struct MENU_ENTRY *act_menu[];
Damit wird ein Zeiger *act_menu auf ein Array von structs vom Typ
MENU_ENTRY deklariert, wobei das auch so nicht funktioniert, da eine
Array-Deklaration immer entweder eine Anzahl der Array-Elemente oder
eine direkte Definition (also eine Aufzählung der Komponenten)
benötigt. Also mindestens mal
struct MENU_ENTRY *act_menu[ANZAHL];
oder so ähnlich.
Abgesehen davon schreibst Du in der struct-Deklaration
INT Max_Ct;
Da C Case-sensitiv ist, klappt das so nicht. Anstelle von "INT" muss
"int" da hin!
Das Beste dürfte sein, Du schaust mal in Deinem C-Buch nach, wie
Strukturen und Arrays deklariert bzw. definiert werden.
Die Strukturen sollten funktionieren, in einem kleineren Menü ohne
Untermenüs gibt es keine Probleme und da arbeite ich mit einer
ähnlichen Typendefinition.
// Definition of Menu entrys
static const char menu_str0[] PROGMEM = "Eintrag 1";
static const char menu_str1[] PROGMEM = "Eintrag 2";
static const char menu_str2[] PROGMEM = "Eintrag 3";
static const char menu_str3[] PROGMEM = "Eintrag 4";
typedef struct MENU {
const unsigned char *text;
INT next;
void ( *fp )(void);
} MENU_ENTRY;
const MENU_ENTRY menue[] ={
{ menu_str0, 0, func0 },
{ menu_str1, 0, func1 },
{ menu_str2, 0, func2 },
{ menu_str3, 0, func3 }
};
void update_menue(void)
{
if( get_key_press( 1<<KEY_UP ))
{
MENU_COUNT ++;
}
if( get_key_press( 1<<KEY_DWN ))
{
MENU_COUNT --;
}
if( MENU_COUNT > 3) MENU_COUNT = 3;
if( MENU_COUNT < 0) MENU_COUNT = 0;
if( get_key_press( 1<<KEY_ENT ))
{
//Aufruf der zugehörigen Funktion
menue[MENU_COUNT].fp();
}
if( MENU_COUNT != MENU_COUNT_OLD )
{
lcd_clrscr();
lcd_gotoxy(1,0);
strcpy_P(HelpStr, (menue[MENU_COUNT].text));
lcd_puts(HelpStr);
MENU_COUNT_OLD = MENU_COUNT;
}
/*Da C Case-sensitiv ist, klappt das so nicht. Anstelle von "INT"
muss
"int" da hin!*/
Stimmt, habe ich vergessen zu schreiben, im Header wird INT als "int"
definiert.
Ich habe nur das Problem, dass ich mit act_menue nicht auf die
verschiedenen Menüs zugreifen kann ohne Fehler aufzuwerfen.
Ah, jetzt verstehe ich auch, was das mit dem typedef sollte... Ist in
meiner Erfahrung eher unüblich, das so zu schreiben, deshalb war ich
drüber gestolpert.
Das erste was du mal tun solltest:
Schmeiss mal alle Casts raus. Eigentlich solltest du
nirgends einen Cast brauchen. Noch steig ich nicht ganz
durch was du da eigentlich geschrieben hast und wie das
alles zusammenhängen soll. Allerdings:
MENU_t *act_menu[];
macht was anderes als das was du wahrscheinlich vorgehabt hast:
act_menu ist ein Array von Pointern auf MENU_t
Ich denke, du möchtest eigentlich haben, dass act_menu
lediglich ein Pointer auf ein MENU_t (oder ein Array von MENU_t)
darstellt.
MENU_t *act_menu;
Ich werd den Code noch weiter durchschauen und versuchen ihn zu
verstehen.
Über act_menue möchte ich den Zugriff auf das jeweils aktuelle Menü
machen d.h.:
act_menue = MENU_MAIN - die Menüpunkte vom Hauptmenü werden angezeigt
act_menue = MENU_SET - die Menüpunkte vom Menü Einstellungen werden
gezeigt...
wenn ich statt act_menue direkt mit dem Menünamen ersetze
(z.B.MENU_SET) wird das Menü Einstellungen angezeigt.
Ich weiß nur nicht wie ich die Zuweisung des aktuellen Menüs auf
act_menue machen kann.
Gruß Daniel
Das hier
> if( MENU_COUNT > act_menue[MENU_COUNT].Max_Ct) MENU_COUNT => act_menue[MENU_COUNT].Max_Ct;
geht sowieso schon mal nicht. Wenn MENU_COUNT zu gross geworden
ist, dann kannst du das nicht prüfen indem du auf
act_menue[MENU_COUNT].Max_Ct
zugreifst. MENU_COUNT ist bereits zu gross und damit geht die
Array Indizierung in die Hose.
Du solltest dir mal die Frage stellen, ob dein Strukturaufbau
sinnvoll ist. Zb. Stelle ich dir die Frage: Warum steht
eigentlich bei jedem MENU_ENTRY dabei, wieviele MENU_ENTRY
dieses Menue aufbauen? Das hat doch nichts in einem MENU_ENTRY
verloren (der ja einen Menuepunkt darstellt), sondern ist
eine Eigenschaft des Menues an sich (fuer welches du keine
Strktur hast).
Ich schlage mal folgende Änderung vor:
typedef void (*MenuFnct)(void);
struct MENU;
struct MENU_ENTRY
{
const unsigned char *Entry_Name;
MENU *SubMenu;
MenuFnct Function;
};
struct MENU
{
const unsigned char *Menu_Name;
int NrEntries;
MENU_ENTRY *Entries;
};
Damit baust du die Einträge für die SubMenues:
const struct MENU_ENTRY MENU_SET_ENTRIES[] ={
{ set1_str, NULL, func0 },
{ set2_str, NULL, func1 }
};
const struct MENU_ENTRY MENU_PAR_ENTRIES[] ={
{ par1_str, NULL, func2 },
{ par2_str, NULL, func3 }
};
Soweit, so gut.
Jetzt werden die eigentlichen Menues aufgebaut:
const struct MENU MENU_SET = {
menu_set_str,
sizeof( MENU_SET_ENTRIES ) / sizeof( *MENU_SET_ENTRIES ),
MENU_SET_ENTRIES
};
const struct MENU MENU_PAR[] = {
menu_par_str,
sizeof( MENU_PAR_ENTRIES ) / sizeof( *MENU_PAR_ENTRIES ),
MENU_PAR_ENTRIES
};
Auch noch nichts überaschendes. Schau dir auch noch mal genau
an, was wo definiert wird. Jetzt macht das alles Sinn.
In einem Menü ist der Titel nur einmal gespeichert. Ein Menü
weiss wieviele Einträge es hat und es besitzt einen Pointer
zu den Einträgen.
Jeder Eintrag wiederum hat einen anzuzeigenden Text, einen
Pointer auf ein mögliches SubMenü und einen Funktionspointer auf
die Funktion.
Jede Information ist nur einmal angegeben, was ein Indiz dafür
ist, dass die generelle Struktur schon mal nicht so schlecht ist.
Lass uns noch das Hauptmenü aufbauen.
Wieder, wir brauchen die Einträge selbst:
const struct MENU_ENTRY MENU_MAIN_ENTRIES[] ={
{ menu_set_str, MENU_SET, NULL },
{ menu_par_str, MENU_PAR, NULL }
};
Mit diesen Einträgen bauen wieder das eigentliche Menu auf:
const struct MENU MENU_MAIN {
menu_main_str,
sizeof( MENU_MAIN_ENTRIES ) / sizeof( *MENU_MAIN_ENTRIES ),
MENU_MAIN_ENTRIES
};
und zuguter letzt haben wir noch den Pointer
auf das zunächst oberste Menü:
struct MENU *ActMenu = MENU_MAIN;
(Ich schicke das jetzt mal ab, damit der Text nicht verloren geht
falls was passiert, weiter gehts im nächsten Posting)
ActMenu zeigt auf das aktuelle Menu.
Du wirst mal eine Funktion brauchen, die ein Menü ausgibt.
Da ich nicht weiss wo du die Ausgabe machst, gebe ich die
Texte einfach mit printf aus. Das musst du dann an deine
Gegebenheiten anpassen.
Also ein Code der das aktuelle Menu anzeigt:
void ShowMenu( MENU* TheMenu )
{
// zuerst den Titel ausgeben
// das ist leicht, der steht in der Menu Struktur selbst
// drinnen. TheMenu ist ein Pointer auf das gewünschte Menu
printf( "%s\n", TheMenu->MenuName );
// Danach kommen alle Einträge dieses Menüs
for( i = 0; i < TheMenu->NrEntries; ++i )
printf( "%s\n", TheMenu->Entries[i].EntryName );
// Das wars dann auch schon. Schau dir genau an, wann ein ->
// kommt und wann ein .
// Wenn du das verstanden hast, ist das schon mal die halbe
// Miete
}
Als nächstes deine Auswertefunktion
int ActEntry; // Nummer des aktuell ausgewählten
// Menüpunktes im Aktuellen Menü
void update_menue(void)
{
if( get_key_press( 1<<KEY_UP )) // Taste + gedrückt?
ActEntry++;
if( get_key_press( 1<<KEY_DWN )) // Taste - gedrückt?
ActEntry--;
if( ActEntry < 0 )
ActEntry = 0;
if( ActEntry >= ActMenu->NrEntries;
ActEntry = ActMenu->NrEntries - 1;
if( get_key_press( 1<<KEY_ENT )) { // Taste Enter gedrückt?
//
// Den selektierten Menüpunkt mal besser zugreifbar
// machen. Das vereinfacht im weiteren die Syntax erheblich
// (und ist auch schneller)
//
MENU_ENTRY *SelectedEntry = ActMenu->Entries[ ActEntry ];
// Hat dieser Eintrag selber ein SubMenu
if( SelectedEntry->SubMenu != NULL ) {
ActMenu = SelectedEntry->SubMenu;
ActEntry = 0;
ShowMenu( ActMenu );
}
// hat er kein SubMenu, bleibt noch der Fall, dass eine
// Funktion aufzurufen sein koennte
else if( SelectedEntry->Function != NULL ) {
SelectedEntry->Function();
}
}
}
Dein Menü hat übrigens einen Schönheitsfehler:
Wenn ich mal in einem Sub-Menü drinnen bin, wie komme
ich wieder zurück?
Warnung: Ich habe den Code direkt im Web-Browser geschrieben.
Es ist also möglich (und wahrscheinlich), dass da Tippfehler drinnen
sind.
Da haben wir schon den ersten
> MENU_ENTRY *SelectedEntry = ActMenu->Entries[ ActEntry ];
das muss heissen:
MENU_ENTRY *SelectedEntry = & ActMenu->Entries[ ActEntry ];
@ Karl Heinz
/*Dein Menü hat übrigens einen Schönheitsfehler:
Wenn ich mal in einem Sub-Menü drinnen bin, wie komme
ich wieder zurück?*/
Dazu will ich das gleichzeitige Drücken der Tasten Auf und Ab als
Escape-Befehl verwenden, damit dann wieder zum Hauptmenü wechseln.
Gruß Daniel
Ich denke Karl Heinz meinte nicht, wie du den Benutzer das Menü
zurückspringen lässt, sondern wie der Vorgang innerhalb deiner
Verketteten Liste gehen soll.
->Man könnte die Liste doppelt verketten. Sprich: Ein Pointer zum
Submenü (wie bisher geschehen) und im Submenü wiederum ein Pointer
zum Parent-Menü.
Hallo,
ich habe heute das Ganze ausprobiert, leider läuft es aber noch nicht.
@ Karl Heinz, kannst Du bitte nochmal mit reinschauen? Die
entsprechenden Fehlermeldungen habe ich mit reingeschrieben.
//typedef void (*MenuFnct)(void);
struct MENU;
struct MENU_ENTRY
{
const unsigned char *Entry_Name;
struct MENU *SubMenu;
void ( *Function )(void);
//struct MenuFnct *Function;
};
>> Den Funktionspointer musste ich in die struct verlegen
struct MENU
{
const unsigned char *Menu_Name;
int NrEntries;
struct MENU_ENTRY *Entries;
};
const struct MENU_ENTRY MENU_SET_ENTRIES[] ={
{ set1_str, NULL, func0 },
{ set2_str, NULL, func1 }
};
const struct MENU_ENTRY MENU_PAR_ENTRIES[] ={
{ par1_str, NULL, func2 },
{ par2_str, NULL, func3 }
};
const struct MENU MENU_SET ={
menu_set_str,
sizeof( MENU_SET_ENTRIES ) / sizeof( *MENU_SET_ENTRIES ),
MENU_SET_ENTRIES
};
>> warning: initialization discards qualifiers from pointer target
type
const struct MENU MENU_PAR ={
menu_par_str,
sizeof( MENU_PAR_ENTRIES ) / sizeof( *MENU_PAR_ENTRIES ),
MENU_PAR_ENTRIES
};
>> warning: initialization discards qualifiers from pointer target
type
const struct MENU_ENTRY MENU_MAIN_ENTRIES[] ={
{ menu_set_str, MENU_SET, NULL },
{ menu_par_str, MENU_PAR, NULL }
};
error: initializer element is not constant
error: (near initialization for `MENU_MAIN_ENTRIES[0].SubMenu')
error: initializer element is not constant
error: (near initialization for `MENU_MAIN_ENTRIES[0]')
error: initializer element is not constant
error: (near initialization for `MENU_MAIN_ENTRIES[1].SubMenu')
error: initializer element is not constant
error: (near initialization for `MENU_MAIN_ENTRIES[1]')
const struct MENU MENU_MAIN = {
menu_main_str,
sizeof( MENU_MAIN_ENTRIES ) / sizeof( *MENU_MAIN_ENTRIES ),
MENU_MAIN_ENTRIES
};
>> warning: initialization discards qualifiers from pointer target
type
//Pointer auf das zunächst oberste Menü:
struct MENU *ActMenu = MENU_MAIN;
>> error: incompatible types in initialization
error: initializer element is not constant
Ich glaube ich bin langsam code-blind geworden.
Gruß
Daniel
> //typedef void (*MenuFnct)(void);> struct MENU;>> struct MENU_ENTRY> {> const unsigned char *Entry_Name;> struct MENU *SubMenu;> void ( *Function )(void);> //struct MenuFnct *Function;> };>>> Den Funktionspointer musste ich in die struct verlegen
Ja, ok. Macht keinen Unterschied. Der typedef da oben haette
Tipparbeit gespart wenn dieser Funktionspointertyp öfter
vorkommt.
> struct MENU
{
> const unsigned char *Menu_Name;> int NrEntries;> struct MENU_ENTRY *Entries;> };>> const struct MENU_ENTRY MENU_SET_ENTRIES[] ={> { set1_str, NULL, func0 },> { set2_str, NULL, func1 }> };>> const struct MENU_ENTRY MENU_PAR_ENTRIES[] ={> { par1_str, NULL, func2 },> { par2_str, NULL, func3 }> };>> const struct MENU MENU_SET ={> menu_set_str,> sizeof( MENU_SET_ENTRIES ) / sizeof( *MENU_SET_ENTRIES ),> MENU_SET_ENTRIES> };>>>> warning: initialization discards qualifiers from pointer target
Bei solchen Fehlermeldungen dreht es sich meistens um
const / nicht const - Dinge
Schaun wir mal. menu_set_str wirds nicht sein. Also der
Pointer auf MENU_SET_ENTRIES.
MENU_SET_ENTRIES ist definiert als
const struct MENU_ENTRY MENU_SET_ENTRIES[]
also mit const.
In der Struktur ist der entsprechende Pointer deklariert als:
struct MENU_ENTRY *Entries
also ohne const.
Jetzt steckt der Compiler in der Klemme: Auf der einen Seite
teilst du ihm mit, dass sich MENU_SET_ENTRIES niemals aendern
wird. Daher das const, und das ist auch gut so, wann immer du
versuchst in diesem Array irgendwas zu ändern klopft dir der
Compiler auf die Finger: Das Array ist const, du kannst dort nichts
aendern.
Auf der anderen Seite versuchst du einen Alternativen Zugriffsweg
über den Pointer Entries aufzubauen, der nicht const ist. D.h
über diesen Pointer wäre eine Änderung in diesem Array möglich.
Tja. Und das teilt der Compiler mit.
> const struct MENU MENU_PAR ={> menu_par_str,> sizeof( MENU_PAR_ENTRIES ) / sizeof( *MENU_PAR_ENTRIES ),> MENU_PAR_ENTRIES> };>>>> warning: initialization discards qualifiers from pointer target> type
Selbiges hier
> const struct MENU_ENTRY MENU_MAIN_ENTRIES[] ={> { menu_set_str, MENU_SET, NULL },> { menu_par_str, MENU_PAR, NULL }> };>> error: initializer element is not constant> error: (near initialization for `MENU_MAIN_ENTRIES[0].SubMenu')> error: initializer element is not constant> error: (near initialization for `MENU_MAIN_ENTRIES[0]')> error: initializer element is not constant> error: (near initialization for `MENU_MAIN_ENTRIES[1].SubMenu')> error: initializer element is not constant> error: (near initialization for `MENU_MAIN_ENTRIES[1]')
Ich denke mal, das ist ähnlich gelagert.
const / non const.
Wenn du obiges korregiert hast (falls du es noch nicht erraten
hast, mach einfach den Pointer Entries zu einem Pointer auf
const
const struct MENU_ENTRY *Entries;
), denke ich muesste dieser Fehler alleine verschwinden. Wenn nicht
melde dich noch mal.
> const struct MENU MENU_MAIN = {> menu_main_str,> sizeof( MENU_MAIN_ENTRIES ) / sizeof( *MENU_MAIN_ENTRIES ),> MENU_MAIN_ENTRIES> };>> >> warning: initialization discards qualifiers from pointer target> type
Ja das kennen wir schon.
> //Pointer auf das zunächst oberste Menü:>> struct MENU *ActMenu = MENU_MAIN;>> >> error: incompatible types in initialization> error: initializer element is not constant>
Ist dasselbe in Grün: MENU_MAIN ist eine const Struktur, also
muss der Pointer auch auf eine const Struktur zeigen:
const struct MENU *ActMenu = MENU_MAIN;
> Ich glaube ich bin langsam code-blind geworden.
Wenn du noch nicht so fit damit bist: lass die const einfach
mal alle weg. const-korrektes arbeiten ist zwar nicht so schwer,
ist aber wie ein Rattenschwanz: Ein Fehler zieht eine ganze
Lawine nach sich.
> //typedef void (*MenuFnct)(void);> struct MENU;>> struct MENU_ENTRY> {> const unsigned char *Entry_Name;> struct MENU *SubMenu;> void ( *Function )(void);> //struct MenuFnct *Function;> };>>> Den Funktionspointer musste ich in die struct verlegen
Jetzt seh ich's erst. Du hast das deswegen gemacht, weil du
einen Fehlermeldung bekommen hast.
Schau dir den typedef noch mal genau an:
> //typedef void (*MenuFnct)(void);
^
|
hier
MenuFnct ist bereits ein Pointer! Daher ist das hier:
> //struct MenuFnct *Function;
die Dekleration eines Pointers auf einen Pointer auf eine Funktion.
Dem die Adresse einer Funktion zuzuweisen klappt klarerweise nicht.
Du brauchst einen Pointer auf eine Funktion. Nun der Datentyp
'MenuFnct' ist bereits als Pointer Datentyp definiert worden.
Daher:
struct MenuFnct Function;
^
|
Hier kein * mehr!
Ich denke schon, die Anzahl der Einträge wird aus der Gesamtgröße aller
Einträge geteilt durch die Einzelgröße der Einträge(Pointer) errechnet
und in die Struct eingetragen. Stimmt das??
Ja, das stimmt so.
Man haette auch schreiben können
sizeof( MENU_SET_ENTRIES ) / sizeof( MENU_SET_ENTRIES[0] );
das ist der übliche Weg, wie man die Anzahl an Einträgen
in einem Array vom Compiler ermitteln kann.
int ai[10];
int size = sizeof( ai ) / sizeof( ai[0] );
Wichtig ist nur: Dazu muss das Array auch als Array sichtbar
sein. Im folgenden Fall
void foo( int bi[] )
{
int i = sizeof( bi ) / sizeof( bi[0] );
}
geht das ganz grauslich schief, weil in der Funktion das Array
bereits zu einem Pointer auf das erste Arrayelement degeneriert
ist. sizeof( bi ) ist hier nicht die Bytegröße des Arrays,
sondern die Bytegröße des Pointers!
Hüte dich auch davor so zu schreiben:
int size = sizeof( ai ) / sizeof( int );
Das sieht harmlos aus, aber wenn du je den Datentyp von ai änderst:
long ai[10];
und vergisst die Berechnung anzupassen
int size = sizeof( ai ) / sizeof( int );
dann geht das furchtbar schief :-) Besser ist es, den eigentlichen
Datentyp aus der Berechnung herauszulassen und den vom Array selbst
abzunehmen.
int size = sizeof( ai ) / sizeof( *ai );
oder
int size = sizeof( ai ) / sizeof( ai[0] );
Hallo Daniel,
bin auf der Suche nach einem geeigneten Ansatz für ein Displaymenü über
die obigen Beiträge gestolpert. Leuchtet mir soweit auch ein, nur habe
ich das Problem wenn ich's so realisiere, dass ums verrecken keine
Anzeige auf dem Display erscheint.
update_display() übergibt HelpStr an lcd_puts().
Wie ist den HelpStr deklariert?
Mein lcd_puts() und lcd_putchar() schaut folgendermaßen aus:
void lcd_puts(unsigned char *s)
{
while (*s)
lcd_putchar (*s++);
}
void lcd_putchar(unsigned char value)
{
LCD_RS = LCD_DATA_REG;
lcd_data_write((value>>4)& 0x0F);
lcd_data_write(value & 0x0F);
delay(4);
return;
}
Übergeb ich nun z.B: lcd_puts("Test"); wird Test auch wunderbar
dargestellt. In der Debugsimulation funzt auch die Menügeschichte mit
Pointerübergabe usw. nur in der realen Schaltung klappts nicht. Eine
Idee?
Also ich nutze eine leicht angepasste lcd lib von P. Fleury.
Da sieht die Funktion lcd puts so aus:
void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
register char c;
while ( (c = *s++) ) {
lcd_putc(c);
}
...ist ja schon mal nix anderes.
Help_Str ist als char array mit der Größe der Display Zeile
deklariert(char HelpStr[20];)
ist die string.h mit eingebunden?
hast Du schon mal das probiert:
snprintf(HelpStr, "Test");
lcd_puts(HelpStr);
Hallo Daniel,
ich werde langsam zum Hirsch... was ich auch probiere, es funzt einfach
nicht. Sicher ist, dass es ein Pointerproblem sein muss. Übergebe ich
nämlich:
strcpy(HelpStr, "test");
anstelle
strcpy(HelpStr, ActMenu->Menu_Name);
wird das einwandfrei dargestellt.
Was mir aufgefallen ist:
Einer als const unsigned char* deklarierten Variable wird ein const
char* zugewiesen. Sollte soweit ja eigentlich kein Problem sein.
Komischerweise erhalte ich nicht einmal eine Compilerwarnung.
Es muss aber irgendwo vielleicht noch an anderer Stelle einen s.g.
"pointer missmatch", geben den ich übersehe, der viel schlimmer ist.
Welchen Compiler verwendest Du denn? Ich nutze Keil uVision C51.
Vielleicht kannst Du ja mal so frei sein und mir Dein lauffähiges Menü
mit zugehörigen Displaydateien schicken, vielleicht sehe ich dann noch
was, was ich bisher übersehen habe.
Wenn ich das gnaze Debugge (halt nur über Software Emulation, geht's
einwandfrei, nur die HW will nicht.
Hallo Karl Heinz,
habe mal ein kleines Proggi angehängt. Im Grunde entspricht es der
Vorlage und im ganzen verstehe ich auch wie's funktionieren soll. Geht
halt nur nicht. Ist ja nicht wirklich viel Code. Bekomme auch keine
Compilerfehler angeziegt, evtl. ist's eine Einstellung die ich noch
nicht entdeckt habe. Vielleicht siehst Du den Knackpunkt auf Anhieb,
bei mir gehen die Scheuklappen runter.
Gruß Derek
Hallo Derek,
anbei ein lauffähiges Programm von mir (Du musst noch Header und c-file
auseinander kopieren)
Ich nutze Programmers Notepad2 und WINAVR.
Ansosnsten kann ich im code auch nichts entdecken.
PROGMEM legt die Daten im Flash ab. Das spart also kostbaren
Speicher im SRAM.
Daniel hat das so gemacht und hat auch sein Program so angepasst,
dass die entscheidende Funktion das weiss.
Genau aus diesem Grund verwendet er das Hilfsarray und kopiert
mittels strcpy_P zuerst vom Flash in dieses Hilfsarray und
von dort weiter zum LCD.
Derek hat das zunächst noch nicht so gemacht. Eigentlich könnte
er sich das Hilfsarray einsparen. Muss er aber nicht. Da die
Texte nicht im Flash liegen, verwendet er folgerichtig auch
keinen strcpy_P sondern einen normalen strcpy.
Soweit ist das alles richtig.
Hallo Karl Heinz,
habe nochmal ein weng rumgespielt und dabei festgestellt, sobald ich
die
const struct MENU_ENTRY MENU_MAIN_ENTRIES[]
und
const struct MENU MENU_MAIN[]
und
const struct MENU *ActMenu = &MENU_MAIN;
nicht mehr global, sondern in
void mnu_update_display(void)
definiere das Proggi funzt. So kann ich's halt nicht gebrauchen. Aber
immerhin habe ich eine Spur.
Hallo
habe mein Pointerproblem gelöst. Das Problem bestand darin, dass ich
dem Compiler/Locater nicht genügend internes Prozessorram zur Verfügung
gestellt habe um die Structuren anzulegen. Nachdem ich das Programm auf
die Displayanzeige zusammengestrichen und den Compiler/Locater
gezwungen habe bestimmte RAM Bereiche zu nutzen bekam ich die helfende
Fehlermeldung. Nutze einen Analog Devices Microconverter 8052 Derivat
mit 265 Byte Near RAM und 2k Far XRAM. Das XRAM sollte genutzt werden,
war aber in der Startupdatei mit 0Btye angegeben. Komischerweise gabs
keinen Compiler, bzw. Locaterfehler und der Debugger hat auch nicht
gemeckert, sondern so getan als ob alles OK wäre. Jetzt gehts. War eine
schwere Geburt, aber habe viel über den Prozessor gelernt.
Gruß Derek