Pointer auf String im Flash

Gast #366390
Lesenswert?
• ▲
▼
Hallo,
ich habe ein Problem mit dem zeichenweise auslesen eines Strings aus
dem Flashspeicher eines AVR.
Den Text im Flash habe ich so angelegt:
1
const char h1[] PROGMEM= "Hallo, ich bin aus dem Flash";
Die Zeichen sollen über die serielle Schnittstelle ausgegeben werden,
was ich bis jetzt so gemacht habe:
1
for (i = 0; i < strlen_P(h1); i++) {
2
  zeichen = pgm_read_byte(&(h1[i]));   
3
  uputchar(zeichen);
4
}
So funktioniert es. Normalerweise mache ich sowas in einer Funktion mit
Pointerarithmetik, was jedoch nicht funktioniert:
1
char *ptr_h1;
2
ptr_h1 = h1;
3

4
while (*ptr_h1) {
5
  zeichen = pgm_read_byte(ptr_h1);  
6
  uputchar(zeichen);
7
  *ptr_h1++;
8
}
Dann werden bei mir teilweise Zeichen gesendet die im String h1 so
nicht drinstehen, aber wieso?
Gast #366394
Lesenswert?
• ▲
▼
Irgenwie scheint es einem selber weiterzuhelfen wenn man das Problem
aufschreibt.
Der Fehler liegt bei mir in der Zeile:
while (*ptr_h1)
Das Zeichen kann aus dem Flash ja nur mittels pgm_read_byte ausgelesen
werden. So wie ich es programmiert habe wird er wohl irgendwas aus dem
RAM auslesen bis da zufällig mal eine \0 drinsteht.
Mit
1
while (zeichen = pgm_read_byte(ptr_h1)) {
2
  uputchar(zeichen);
3
  *ptr_h1++;
4
}

geht es jetzt. Trotzdem Danke.
Gast #366395
Lesenswert?
• ▲
▼
1
      while (zeichen = pgm_read_byte(ptr_h1)) {
2
      uputchar(zeichen);
3
      *ptr_h1++;
4
      }

sollte sein
1
      while (zeichen = pgm_read_byte(ptr_h1)) {
2
      uputchar(zeichen);
3
      ptr_h1++;
4
      }

oder kurz
1
      while (zeichen = pgm_read_byte(ptr_h1++))
2
          uputchar(zeichen);
Moderator Persönliche Seite #366397
Lesenswert?
• ▲
▼
Bei *ptr_h1++ ist der * nur sinnlos, da er einen Zeiger
dereferenziert, um das Ergebnis danach wegzuwerfen.  Falls
der Zeiger als "volatile" markiert wäre, würde der Compiler
das Dereferenziern sogar wirklich ausführen, so kann er es
wegwerfen.  Wenn er gut ist, schmeißt er noch 'ne Warnung
(computed value is not used oder sowas).
Gast #366398
Lesenswert?
• ▲
▼
Warnung bekomme ich an dem Punkt keine.
An der Zeile
ptr_h1 = h1;
gibts jedoch ein Warning "assignment discards qualifiers from pointer
target type".
Und dies auch wenn ich mal probeweise den Qualifier const weglasse.
Gast #366399
Lesenswert?
• ▲
▼
Typ(const char [] PROGMEM) != Typ(char *);

Da musst du ptr_h1 als PGM_P definieren, dann geht das ohne Warnung.
PGM_P ptr_h1; /* PGM_P: siehe avr/pgmspace.h */

Warum das mit "pgm_read_byte(ptr_h1)" nicht geht ist etwas
komplizierter und liegt daran wie der Flash-Speichertype (und der
Zugriff darauf) über Makros definiert ist. Du solltest hier eigentlich
immer das Format &h1[index] verwenden, auch wenn der index immer fest 0
ist und das Ergebnis aus C Syntax-Sicht identisch ist. Aber wegen der
Art wie AVR-GCC diesen Ausdruck auswertet (und auch muss, sonst würden
es nicht funktionieren) ergibt sich zwingend dieses Format.
1
      while (zeichen = pgm_read_byte(&ptr_h1[0])) {
2
         uputchar(zeichen);
3
         ptr_h1++;
4
      }
Das ist nur etwas mehr Schreibarbeit, die Effektivität des generierten
Maschinencodes leidet darunter nicht, es wird nicht erst 0 zum Zeiger
addiert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren