Forum: Compiler & IDEs Pointer auf String im Flash


von Thomas (Gast)


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?

von Timmo H. (masterfx)


Lesenswert?

Also die Variable schein ja bekannt zu sein, warum machst du dann nicht
einfach so:
1
char i=0;
2
while(hl[i]){
3
  uputchar(hl[i++]);
4
}

von Timmo H. (masterfx)


Lesenswert?

Ahh sehe es gerade, beim Atmel geht das ja gar nicht. Ihh, hab das bis
jetzt nur mit nem Motorola gemacht da ist das Teilweise besser.

von Timmo H. (masterfx)


Lesenswert?

Dein Fehler ist glaub ich die Zeile
1
*ptr_h1++;
ich weiss jetzt nicht mehr die Priorität, aber ich glaube du
inkrementierst nur den Inhalt des Speicherbereichs (was ja nicht geht).
Also
1
ptr_h1++;

von Thomas (Gast)


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.

von Orakel (Gast)


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);

von Thomas (Gast)


Lesenswert?

Hm, funktioniert sogar beides, also *ptr_h1++ und ptr_h1++.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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).

von Thomas (Gast)


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.

von Werner B. (Gast)


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.

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.