mikrocontroller.net

Forum: Compiler & IDEs Pointer auf String im Flash


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
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:
for (i = 0; i < strlen_P(h1); i++) {
  zeichen = pgm_read_byte(&(h1[i]));   
  uputchar(zeichen);
}
So funktioniert es. Normalerweise mache ich sowas in einer Funktion mit
Pointerarithmetik, was jedoch nicht funktioniert:
char *ptr_h1;
ptr_h1 = h1;

while (*ptr_h1) {
  zeichen = pgm_read_byte(ptr_h1);  
  uputchar(zeichen);
  *ptr_h1++;
}    
Dann werden bei mir teilweise Zeichen gesendet die im String h1 so
nicht drinstehen, aber wieso?

Autor: Timmo H. (masterfx)
Datum:

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

Autor: Timmo H. (masterfx)
Datum:

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

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Fehler ist glaub ich die Zeile
*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
ptr_h1++;

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
while (zeichen = pgm_read_byte(ptr_h1)) {
  uputchar(zeichen);
  *ptr_h1++;
} 

geht es jetzt. Trotzdem Danke.

Autor: Orakel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
      while (zeichen = pgm_read_byte(ptr_h1)) {
      uputchar(zeichen);
      *ptr_h1++;
      } 

sollte sein
      while (zeichen = pgm_read_byte(ptr_h1)) {
      uputchar(zeichen);
      ptr_h1++;
      } 

oder kurz
      while (zeichen = pgm_read_byte(ptr_h1++))
          uputchar(zeichen);

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, funktioniert sogar beides, also *ptr_h1++ und ptr_h1++.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

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

Autor: Thomas (Gast)
Datum:

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

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
      while (zeichen = pgm_read_byte(&ptr_h1[0])) {
         uputchar(zeichen);
         ptr_h1++;
      } 
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

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.