Mehrdimensionales String-Array im Flash

OP #555232
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!
Gast #555280
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
Gast #555476
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
OP #556041
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!
#556086
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.
#556159
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

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.