www.mikrocontroller.net

Forum: Compiler & IDEs Mehrdimensionales String-Array im Flash


Autor: Günther Frings (taraquedo)
Datum:

Bewertung
0 lesenswert
nicht 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:
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!

Autor: Joerg X. (Gast)
Datum:

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

wahrscheinlich bist du mit einem Array von Pointern besser bedient

Autor: Branko Golubovic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeichenketten im Flash initialisieren(Beispiel):
const unsigned char noise_reduction_message[5][30]PROGMEM={
{"Keine                        "},
{"Aufsummierung                "},
{"Kontinuerliche Mittelung     "},
{"Gewichtete Aufsumierung      "},
{"Unterduckung von Extremwerten"}};

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

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

Branko

Autor: Günther Frings (taraquedo)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define NBOFCMDS 3
const char cmd_one[] PROGMEM = "foo";
const char cmd_two[] PROGMEM = "bar";
const char cmd_three[] PROGMEM = "foobar";

const char* cmd[NBOFCMDS] PROGMEM = {
  cmd_one,
  cmd_two,
  cmd_three  };

// In einer Funktion lautet der Aufruf dann z.B.:
   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:
Zeiger auf Werte im Flash sind ebenfalls 16 Bits "groß"
(Stand avr-gcc 3.4.x).
Damit ist der mögliche Speicherbereich für "Flash-Konstanten"
auf 64kB begrenzt.

   uint8_t *ptrToArray;
[...]

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

Grüße!

Autor: Frank Jonischkies (frajo)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rene Zimmermann (renezimmermann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
#include <avr/io.h>
#include <stdio.h>
#include <avr/pgmspace.h>
#include <string.h>

const char adr_00001[] PROGMEM = "Zimmer 00001\r\n";
const char adr_00002[] PROGMEM = "Zimmer 00002\r\n";
const char adr_00003[] PROGMEM = "Zimmer 00003\r\n";
const char adr_00004[] PROGMEM = "Zimmer 00004\r\n";
const char adr_00005[] PROGMEM = "Zimmer 00005\r\n";
const char adr_00006[] PROGMEM = "Zimmer 00006\r\n";
const char adr_00007[] PROGMEM = "Zimmer 00007\r\n";
const char adr_00008[] PROGMEM = "Zimmer 00008\r\n";
const char adr_00009[] PROGMEM = "Zimmer 00009\r\n";
const char adr_00010[] PROGMEM = "Zimmer 00010\r\n";

PGM_P p_adr[] PROGMEM = {adr_00001, adr_00002, adr_00003, adr_00004, adr_00005,
adr_00006, adr_00007, adr_00008, adr_00009, adr_00010};

void uart_putc(char c){
    while (!(UCSRA & (1<<UDRE))){}          // warten bis Senden moeglich
    UDR = c;                // sende Zeichen
}
 
void uart_puts_p(const char *text){
    uint8_t Zeichen;
        while ((Zeichen = pgm_read_byte(text))){ 
        uart_putc(Zeichen);
        text++;
    }
}

PGM_P p;

int main(void){
  for (uint8_t z = 1; z < 10; z++){
    memcpy_P(&p, &p_adr[z], sizeof(PGM_P));
    uart_puts_p (p);
  }
  while(1){}
}

Gruß Rene

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.