Hallo,
ich bin im Moment dabei eine Menüstruktur aufzubauen, habe dabei
allerdings Probleme mit Arrays, welche im Progmem abgelegt sind.
Die Arrays sind:
menu[20][10], die erste Dimension ist jeweils ein ganzes Menü, die
Zweite Dimension speichert ab dem zweiten Element den Index für das
Array menu_entry, in welchem der Eintrag ist. Das erste Element gibt die
Größe des Menüs in Menüpunkten an.
menu_entry[50][4], die erste Dimension ist jeweils ein Menüpunkt, die
Zweite Dimension speichert im ersten Element den Index für das
Stringarray, in welchem der String für diesen Menüpunkt steht.
Nun muss ich also zuerst aus dem menu-array den Index für das
menu_entry-array holen, damit ich aus diesem den Index für das
string-array holen kann, um dann eben diesen String anzuzeigen.
Allerdings hakt es da ein wenig, soll heißen ich greife auf die falsche
Adresse zu (komische Zeichen). Übrigens habe ich erstmal nur das
menu-array in den Progmem gelegt, weil ich teilweise umsteigen wollte
(wenn beide arrays "normal" habe ich das hingekriegt).
1
voidlcd_write_menu(uint8_tp_menu)
2
{
3
4
PGM_Pl_pgmpointer;
5
uint8_tl_index;
6
7
for(uint8_ti=0;i<menu[p_menu][0];i++)
8
{
9
l_pgmpointer=(PGM_P)pgm_read_word(&menu[p_menu][i+1]);//wenn ich hier statt i+1 eine konstante Zahl hinschreibe, funktioniert alles
Christian schrieb:> l_pgmpointer = (PGM_P) pgm_read_word( &menu[p_menu][i+1] ); //wenn ich hier
statt i+1 eine konstante Zahl hinschreibe, funktioniert alles
Probier statt
"(&menu[p_menu][i+1])"
mal die Version ohne doppelte Adressauflösung:
"(menu[p_menu] + i + 1)"
Dadurch steht im Argument von pgm_read_word() gleich eine Adresse. Ein
verschachteltes Array ist ja eigentlich nix anderes als ein
Pointer-Pointer auf ein Word. Die werden vom Compiler nur voneinander
Unterschieden, damit der Benutzer/Programmierer besser zurechtkommt.
Ich vermute nämlich eine "falsche" Makro-Umsetzung innerhalb von
pgmspace, wobei das doch eigentlich auch für zweidimensionale Arrays
gehen sollte?!
mfg mf
Hm schonmal besser als vorher.
Das Menü flimmert jetzt allerdings, er zeigt einmal auf allen
Menüpunkten "Wecker 4" an, was heißen würde er nimmt menu_entry[3][0]
und menu[0][4], weil hier ja der Index 3 drinsteht.
Allerdings flimmern hinter diesen "Wecker 4" Schriftzügen komische
Zeichen, also wieder falsche Speicheradressierung. Ich weiß nur nicht wo
das jetzt herkommt...
Christian schrieb:> Das Menü flimmert jetzt allerdings
Ich hab dein Programm nicht analysiert.
Aber Flimmern auf einem LCD ist meistens ein Zeichen für
Löschen + Neu beschreiben
Und das ständig
Wieso muss vor dem menu[p_menu] eigentlich kein Adress-Operator, ohne
diesen wird doch eigentlich der Inhalt dieses Array-Eintrages
ausgegeben, oder nicht? Trotzdem scheint es so (eher) richtig zu sein,
obwohl das auch so nicht funktioniert.
Erster Eintrag ist Wecker 1, dann komische Zeichen, dann Wecker 4, dann
komische Zeichen, dann Wecker 2, dann zwei Einträge komische Zeichen.
Also zwischendurch wieder falsche Adresse.
Um auf diese Strings zu kommen müsste man zuerst menu[0][1], dann
menu[0][4] und dann menu[0][2] auslesen, wenn man die komischen Zeichen
mal weg lässt.
Irgendwas passt nicht...
Christian schrieb:> Irgendwas passt nicht...
Da passt vieles nicht
Das waren die Daten
1
staticuint8_tmenu_entry[50][4]=
2
{
3
{8,0,0,0},
4
{9,0,0,0},
5
{10,0,0,0},
6
{11,0,0,0},
7
{12,0,0,0},
8
{13,0,0,0},
9
{14,0,0,0}
10
};
11
12
staticuint8_tmenu[20][10]PROGMEM=
13
{
14
{7,0,1,2,3,4,5,6,7}
15
};
was es mit der menu Variablen auf sich hat, hat ich ehrlich gesagt nicht
wirklich auf Anhieb durchschaut. Für meinen Geschmack verwendest du da
ein wenig zu oft zu sehr unstrukturierte uint8_t Arrays, als ob structs
nie erfunden worden wären
1
voidlcd_write_menu(uint8_tp_menu)
2
{
3
4
PGM_Pl_pgmpointer;
5
uint8_tl_index;
6
7
for(uint8_ti=0;i<pgm_read_byte(menu[p_menu]);i++)
Schreibs aus: & menu[p_menu][0]
menu ist ein 2D Array. Und da es sich nicht ändert, ist es eine gute
Idee diesen Wert erst einmal vorab zu bestimen (Dein { Schema macht mich
wahnsinng, das du da noch siehst welche } zu welcher { gehört ...
Respekt )
Sicherheitshalber auch kontrollieren (mit einer Ausgabe) ob da
tatsächlich die 7 daher kommen.
Wie gehts weiter?
{7,0,1,2,3,4,5,6,7}
nach der 7 stehen dann die 7 Nummern der Menüpunkte. Die liest du mit
Wenn du den Überblick verlierst, dan mal dir deine Datenstruktur auf und
verbinde die Einzelteile mit Pfeilen, die dich bei der Programmierung
leiten, was du von wem bekommst und was du damit tun musst.
Noch ein Hinweis:
Man kann sich Indizes (als uint8_t) auch ganz einfach auf einem LCD
ausgeben lassen um zu kontrollieren, ob man das richtige gelesen hat
oder nicht. Alle Indizes müssen genau so aus den entsprechenden Arrays
gelesen werden, wie du sie beim Aufbau der Datenstruktur angegeben hast.
Lediglich Pointerwerte sind eher sinnlos beim Ausgeben.
PS: was sagt der Prefix l_ aus?
Sag jetzt bitte nicht, das der eine lokale Variable kennzeichnet.
Hm, deine Version funktioniert aber auch nicht wie gewollt, es zeigt
mehrmals den Text aus strd[0] an, und dann mehrmals den Text aus
strd[15].
Und eigentlich wollte ich das ganze mit structs machen, allerdings gab
es dabei andauernd Fehlermeldungen, also hab ichs einfach mit ner
zweiten Dimension gelöst.
Und ja, das l_ zeigt eine lokale Variable an. Ich weiß nicht wie das im
Mikrocontroller-Bereich gehandhabt wird, aber vorher habe ich mit Basic
schon für den PC programmiert, da wurde das so gemacht. Wobei Basic und
C natürlich auch wieder nen Unterschied ist...
Ok, hat sich erledigt, das Array menu_entry war noch nicht im Flash
Bereich, weil ich ja schrittweise umstellen wollte...
Aber jetzt ist mir wenigstens alles klar, vielen Dank!
Christian schrieb:> Hm, deine Version funktioniert aber auch nicht wie gewollt, es zeigt> mehrmals den Text aus strd[0] an, und dann mehrmals den Text aus> strd[15].
Tja. Im Gegensatz du dir muss ich blind programmieren.
Du hast die einzelnen Indizes: Gib sie dir am LCD aus.
> Und ja, das l_ zeigt eine lokale Variable an.
Spar dir das.
Christian schrieb:> Ok, hat sich erledigt, das Array menu_entry war noch nicht im Flash> Bereich, weil ich ja schrittweise umstellen wollte...
OK. Hab ich auch übersehen, dass da ein PROGMEM fehlt.
Wie gesagt: Ich muss blind programmieren. Direkt hier im Forum
Eingabefeld. Da passiert schon mal das eine oder andere
Ja, ist mir klar, ist schon schwer genug fremde Codes zu analysieren,
selbst wenn man den gesamten Code vorliegen hat, weil die
Programmierarten/-style schon sehr unterschiedlich sind.
Und den Fehler hab ich auch durch Ausgeben der Indizes auf dem LCD
gefunden. Das mache ich normal auch immer, nur vorher hab ich erst nur
(fälschlicherweise) Pointer verwendet, wo ja eine Ausgabe auf dem
Display normalerweise nicht viel aussagt.