Forum: Compiler & IDEs Mehrdimensionales String-Array im Flash


von Günther F. (taraquedo)


Lesenswert?

Hallo!

Jetzt habe ich schon einiges probiert, aber es kommt immer nur Unsinn 
bei raus. Mein Ziel ist es Zeichenketten im Flash zu speichern. Die 
brauche ich sowohl einzeln, aber auch so, dass ich sie nacheinander 
ausgeben lassen kann. Also ein Array von Zeichenketten. Dann könnte ich 
myvar[0] ansprechen oder myvar[i] und i laufen lassen.

Im Tutorial steht folgendes für eine einzelne Zeichenkette:
1
const char myvar[] PROGMEM = "foo";

Meine Versuche, dieses mehrdimensional auszuweiten und zu initialisieren 
scheiterten. Ich erspare mir an dieser Stelle Beispiele meiner Ideen, 
aber ich erhalte immer den Fehler, dass die Bereiche überlappen.

Wie kann man das machen?

Grüße!

von Joerg X. (Gast)


Lesenswert?

bei mehrdimensionalen arrays musst du alle Längen angeben und alle 
unterarrays müssen gleich groß sein:
1
int8_t array[2][2] = {{12, 78},{90, -5}};
2
char thetest[4][6]={"foo  ", "sowas", "aber ", "auch "};

wahrscheinlich bist du mit einem Array von Pointern besser bedient

von Branko Golubovic (Gast)


Lesenswert?

Zeichenketten im Flash initialisieren(Beispiel):
1
const unsigned char noise_reduction_message[5][30]PROGMEM={
2
{"Keine                        "},
3
{"Aufsummierung                "},
4
{"Kontinuerliche Mittelung     "},
5
{"Gewichtete Aufsumierung      "},
6
{"Unterduckung von Extremwerten"}};

und ausgeben:
1
x=1 ; // Zugrif auf Zeichenkette "Aufsummierung                "
2
printf_P(noise_reduction_message[x]);

Mit x(0 bis 4) kannst du auf bestimmte Zeichenkette zugreifen.

Branko

von Günther F. (taraquedo)


Lesenswert?

Hi!

Durch diese enorme Beschränkung habe ich mich dafür entschieden ein 
Zeigerfeld anzlegen, welches auf meine Konstanten zeigt. Das sieht dann 
so aus:
1
#define NBOFCMDS 3
2
const char cmd_one[] PROGMEM = "foo";
3
const char cmd_two[] PROGMEM = "bar";
4
const char cmd_three[] PROGMEM = "foobar";
5
6
const char* cmd[NBOFCMDS] PROGMEM = {
7
  cmd_one,
8
  cmd_two,
9
  cmd_three  };
10
11
// In einer Funktion lautet der Aufruf dann z.B.:
12
   uart_puts_p((char*)pgm_read_word(cmd+i));

Das klappt auch ganz gut nur denke ich immer noch was falsch gemacht zu 
haben. char* im cmd-Array reserviert doch nur 8bit für die Adressen der 
Konstanten. Aber was, wenn meine Konstanten nun hinter 0xFF fallen? Ich 
bräuchte doch irgendwie uint16_t*, oder?
Auch das Tutorial verstehe ich nicht ganz. Dort steht:
1
Zeiger auf Werte im Flash sind ebenfalls 16 Bits "groß"
2
(Stand avr-gcc 3.4.x).
3
Damit ist der mögliche Speicherbereich für "Flash-Konstanten"
4
auf 64kB begrenzt.
5
6
   uint8_t *ptrToArray;
7
[...]

Widerspricht sich das dann nicht anschließend uint8_t* zu nutzen?

Grüße!

von Frank J. (frajo)


Lesenswert?

Dein (char *) bedeutet dass an der 16 Bit Adresse, die pgm_read_word 
liefert, ein Byte liegt, welches Du dem UART übergibst.

von Karl H. (kbuchegg)


Lesenswert?

Günther Frings wrote:
> Das klappt auch ganz gut nur denke ich immer noch was falsch gemacht zu
> haben. char* im cmd-Array reserviert doch nur 8bit für die Adressen der
> Konstanten.

Nein.
Der Compiler reserviert soviele Bytes wie er benötigt, um dort
einen Zeiger abzulegen. Das char in char * bedeutet, dass
an der Speicheradresse, auf die der Zeiger hinzeigt, ein char
zu finden ist.

> Aber was, wenn meine Konstanten nun hinter 0xFF fallen? Ich
> bräuchte doch irgendwie uint16_t*, oder?

Nein. Du speicherst dort ja keine uint16 ab :-)

Der Compiler weiss schon von sich aus, wieviel Platz er für
einen Zeiger benötigt. Du musst ihm nur noch sagen, worauf
denn der Zeiger zeigt.

von Rene Z. (renezimmermann)


Lesenswert?

Hi,
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <avr/pgmspace.h>
4
#include <string.h>
5
6
const char adr_00001[] PROGMEM = "Zimmer 00001\r\n";
7
const char adr_00002[] PROGMEM = "Zimmer 00002\r\n";
8
const char adr_00003[] PROGMEM = "Zimmer 00003\r\n";
9
const char adr_00004[] PROGMEM = "Zimmer 00004\r\n";
10
const char adr_00005[] PROGMEM = "Zimmer 00005\r\n";
11
const char adr_00006[] PROGMEM = "Zimmer 00006\r\n";
12
const char adr_00007[] PROGMEM = "Zimmer 00007\r\n";
13
const char adr_00008[] PROGMEM = "Zimmer 00008\r\n";
14
const char adr_00009[] PROGMEM = "Zimmer 00009\r\n";
15
const char adr_00010[] PROGMEM = "Zimmer 00010\r\n";
16
17
PGM_P p_adr[] PROGMEM = {adr_00001, adr_00002, adr_00003, adr_00004, adr_00005,
18
adr_00006, adr_00007, adr_00008, adr_00009, adr_00010};
19
20
void uart_putc(char c){
21
    while (!(UCSRA & (1<<UDRE))){}          // warten bis Senden moeglich
22
    UDR = c;                // sende Zeichen
23
}
24
 
25
void uart_puts_p(const char *text){
26
    uint8_t Zeichen;
27
        while ((Zeichen = pgm_read_byte(text))){ 
28
        uart_putc(Zeichen);
29
        text++;
30
    }
31
}
32
33
PGM_P p;
34
35
int main(void){
36
  for (uint8_t z = 1; z < 10; z++){
37
    memcpy_P(&p, &p_adr[z], sizeof(PGM_P));
38
    uart_puts_p (p);
39
  }
40
  while(1){}
41
}

Gruß Rene

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.