Forum: Mikrocontroller und Digitale Elektronik Array of String Arrays


von Miche L. (ihoid)


Lesenswert?

Hi,ich möchte auf meinem LCD eine Menüstruktur mit Untermenüs einbauen.
Hierzu habe ich mir gedacht ich nehme ein 2 Dimensionales String Array,
welches ich im Flash ablege.
Das ganze lässt sich zwar Compilieren, aber nach Abruf des Strings zeigt 
das LCD nur noch mist an.
Nun würde ich gerne von euch wissen, ob folgende Code-Zeilen korrekt 
sind.
Zum einen das Ablegen im Flash:
1
const char menue_unter1_strings[5][4][16] PROGMEM = {
2
  {"AA", "AB", "AC", "AD"}, { "BA", "BB", "BC"}, { "CA", "CB", "CC"}};
und das lesen aus dem Flash und ablegen im Array Buffer (char):
1
strcpy_P (buffer, (const char*) pgm_read_word (menue_unter1_strings[0][1]));
Controller ist ein ATMEGA 644 dürfte also Flashmäßig eigentlich keine 
Probleme geben.

Gruß Miche

von Rainer B. (katastrophenheinz)


Lesenswert?

Hi, das Array landet dadurch zwar im Flash, aber nicht die Zeichenketten 
selber. Guckst du hier:
http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

unter "Storing and Retrieving Strings in the Program Space"

Gruss, Rainer

von Miche L. (ihoid)


Lesenswert?

Danke schon mal,
nun habe ich auch verstanden, warum das so nicht ging ;)
Ich habe nun aber 3 Arrays welche ich wie im Beispiel abespeichert habe.
Jetzt müsste ich also wiederum ein Array i Speicher ablegen, welches die 
Zeiger der Arrays (welche die Zeiger enthalten, die auf die Strings 
zeigen) enthalten.
Wenn ich allerdings so verfahre und es mit:
1
 
2
PGM_P ...[] PROGMEM = { strarray1, strarray2, strarray3};
versuche, so liefert mir der Compiler:
Warning: initialization from incompatible pointer type.
Weiters, wie rufe ich dann solch ein Array auf ( mit ...[][] geht es ja 
wohl kaum)? Ich stehe da irgendwie ein wenig auf der Leitung und bin mit 
Zeigern, wie ich zugeben muss wohl noch nicht so fit.

Gruß

von Rainer B. (katastrophenheinz)


Lesenswert?

Schwer zu sagen, da du die entscheidenden Stellen weggelassen hast.
Was ist srtarray1 .. 3 ?
Poste mal den gesamten Code, der sich auf deine Zeichenketten-Mimik 
bezieht.

Gruss, Rainer

von Georg G. (df2au)


Lesenswert?

Versuch es mal so:

const char str1[] PROGMEM = "123";
const char str2[] PROGMEM = "345";

PGM_P strarray[] = {str1, str2};

int main(void) {

    PGM_P   p;
    char    x;

    p = (PGM_P) pgm_read_word(strarray[1]);
    x = pgm_read_byte(p[2]);

    return(0);
    }

von Rainer B. (katastrophenheinz)


Lesenswert?

>Weiters, wie rufe ich dann solch ein Array auf ( mit ...[][] geht es ja
>wohl kaum)? Ich stehe da irgendwie ein wenig auf der Leitung und bin mit
>Zeigern, wie ich zugeben muss wohl noch nicht so fit.

Wenn du in unserer Lieblingssuchsmaschine einfach mal alle deine 
Keywords eingibst, also z.B. "progmem avr multi dimensional array 
Flash", findest du alle Informationen, die du brauchst und Beispiele, an 
denen du dich orientieren kannst, z.B. hier, sogar mit einer ganz 
ausführlichen Erklärung des Großmeisters KHB.


Beitrag "PROGMEM und 2 dimensionaler array"


Gruss, Rainer

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rainer B. schrieb:
> Hi, das Array landet dadurch zwar im Flash, aber nicht die Zeichenketten
> selber.

Doch tun sie. menue_unter1_strings liegt komplett im Flash.

von Miche L. (ihoid)


Lesenswert?

Ein wie in dem Link beschriebenes 2 Dimensionales Char Array habe ich 
auch schon hinbekommen. Bei mir hakt es allerdings an einem 2 
Dimensionalen String Array oder 3 Dimensionalen Char Array, je nach 
Betrachtungsweise.
meine komplette aktuelle Definition:
1
char UMEN1_1[] PROGMEM = "Adresse";
2
char UMEN1_2[] PROGMEM = "Modus";
3
char UMEN1_3[] PROGMEM = "Busausfall";
4
char UMEN1_4[] PROGMEM = "Adressierung";
5
PGM_P menue_unter1_strings1[] PROGMEM = {UMEN1_1, UMEN1_2, UMEN1_3, UMEN1_4};
6
char UMEN2_1[] PROGMEM = "Programm";
7
char UMEN2_2[] PROGMEM = "Geschwindigkeit";
8
char UMEN2_3[] PROGMEM = "Aktiv";
9
PGM_P menue_unter1_strings2[] PROGMEM = {UMEN2_1, UMEN2_2, UMEN2_3};
10
char UMEN3_1[] PROGMEM = "ROT";
11
char UMEN3_2[] PROGMEM = "GRUEN";
12
char UMEN3_3[] PROGMEM = "BLAU";
13
PGM_P menue_unter1_strings3[] PROGMEM = {UMEN3_1, UMEN3_2, UMEN3_3};
14
PGM_P menue_unter1_strings[] PROGMEM = { menue_unter1_strings1, menue_unter1_strings2, menue_unter1_strings3};
Ich hoffe, so könnt Ihr mich besser verstehen. Und was ich überhaupt 
machen will. Beispiele zu 3 Dimensionalen Arrays habe ich bis jetzt aber 
auch noch fast nicht gefunden.

Gruß Miche

von Rainer B. (katastrophenheinz)


Lesenswert?

Johann L. schrieb:
> Doch tun sie. menue_unter1_strings liegt komplett im Flash.

Tatsächlich! Sorry, da habe ich zu schnell in eine bestimmte Richtung 
gedacht! Dann ist die Lösung ja viel einfacher als gedacht:

Miche, in deiner ersten Lösung nur diese eine Zeile anpassen.
1
strcpy_P (buffer, menue_unter1_strings[0][1]);

Der ganze andere Babel mit Arrays von Zeigern auf Zeichenketten kommt 
erst dann zum Tragen, wenn du Zeichenketten mit unterschiedlicher Länge 
im Flash ablegen willst. Wenn du das nicht brauchst, dann vergiss es.
Und: Danke, Johann.
Gruss, Rainer

: Bearbeitet durch User
von Miche L. (ihoid)


Lesenswert?

Top, Danke schonmal.
Ich weiß zwar nun, dass es tatsächlich funktioniert, nur noch nicht 
genau wie und warum zuvor nicht... Das werde ich mir bei Zeiten wohl 
nochmal ansehen :)

von Rainer B. (katastrophenheinz)


Lesenswert?

..andererseits, du warst ja auf dem Weg "Array von Zeigern auf 
Zeichenketten" auch schon fast fertig.
Das einzige was dir noch fehlt, ist die richtige Initialisierung des 
Array. Das geht genauso wie immer:
1
PGM_P menue_unter1_strings[3][4] PROGMEM = 
2
  { {UMEN1_1, UMEN1_2, UMEN1_3, UMEN1_4}, 
3
    {UMEN2_1, UMEN2_2, UMEN2_3},
4
    {UMEN3_1, UMEN3_2, UMEN3_3} 
5
  };
Der Zugriff auf das passende Element erfolgt genauso wie oben:
1
    strcpy_P(buffer, menue_unter1_strings[1][2]);

>Ich weiß zwar nun, dass es tatsächlich funktioniert, nur noch nicht
>genau wie und warum zuvor nicht... Das werde ich mir bei Zeiten wohl
>nochmal ansehen :)
1
strcpy_P (buffer, (const char*) pgm_read_word (menue_unter1_strings[0][1]));
Dort hast du einmal zuviel dereferenziert
- menue_unter1_strings[0][1] : Liefert die Adresse, an der im Flash 
deine Zeichenkette "AB\0\0\0...." abgelegt ist.
- pgm_read_word Liest den Inhalt dieser Adresse, also die beiden Bytes 
0x41 und 0x42 ( das entspricht A und B )
- (const char *) zwingt den Compiler, das wiederum als einen Zeiger auf 
eine Zeichenkette zu interpretieren, dh. diese beiden Bytes werden jetzt 
als Zeiger, der auf 0x4241 zeigt, interpretiert.
Ab hier geht's also schief.
- strcpy_P versucht dann den Inhalt der Flashspeicherzellen 0x4241 ff in 
den entsprechenden RAM-Bereich von "buffer" zu kopieren, solange bis \0 
gelesen wird.

Du brauchst also das pgm_read_word an dieser stelle nicht, da der 
Compiler weiß, dass menue_unter1_strings im Flash liegt und aus 
menue_unter1_strings[0][1] gleich eine Flash-Adresse macht.

: Bearbeitet durch User
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.