mikrocontroller.net

Forum: Compiler & IDEs Progmem mit Zeigern auf Funktionen


Autor: Michael J. (jogibaer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein kleines Problem mit Progmem.

folgender Kode ( Auszug):

>>>>>>>>>>>>>>>>>>>>>>>


static char  ERROR_USB_RP[]   PROGMEM = "USB Puffer voll";
glcd_write_string_p (ERROR_USB_RP);



/*********************************************************************** 
**********************************************
*Funktion zur Ausgabe eines Strings mit ASCII Zeichen aus dem Flash
*
*Die Zeichen müssen konvertiert werden, da die Anfangsadresse von " " 
die 0 ist ( Datum - 32 )
*  Die Länge des Strings wird durch das Nullbyte festgelegt
*  Die Ausgabe des Strings erfolgt mit dem Blockmodus
*
************************************************************************ 
*********************************************/


unsigned char glcd_write_string_p (char *z_string)
  {
  // Schreiben per Block mit Autoincrement einschalten
  glcd_write_byte (DATA_AUTO_WRITE,'C');
  // Alle Daten per Schleife zum GLCD übertragen, bis das Stringende 
erkannt wird
  while (*z_string != 0)
    {
    // aktuelles Datum aus String lesen, zum GLCD ausgeben
    // und danach den Zeiger auf den String inkrementieren
    glcd_write_byte ( pgm_read_byte (z_string ++) -32 ,'D');
    }
  // Schreiben per Block mit Autoincrement ausschalten
  glcd_write_byte (DATA_AUTO_RESET,'C');
  return 0;
  }

<<<<<<<<<<<<<<<<<<<<

( glcd_write_byte schreibt das jeweilige Datum auf das LCD )

Irgendwie funktioniert dieses nicht.
Eine fast identische Funktion zur Ausgabe eines Strings aus dem
RAM funktioniert tadellos.

-> char *z_string

Wenn ich char zu int mache, funktioniert es teilweise.
char zu klein ? (Inhalt von char die Flashspeicheradresse ?)
Jedes 2. Zeichen wird ausgegeben ( int inkrementieren = Adresse + 2 )
Das wäre ja noch verständlich.

Wie kann ich das am besten lösen, ohne mir ins Knie zu schießen ?


Jogibär

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mehrere Probleme:

 while (*z_string != 0)  <==== Funktioniert nicht!
  steht ja im progmem. Zugriff nur über pgm_read_byte!

    pgm_read_byte (z_string ++);   <=== Das ++ "geht so ab und zu 
nicht".


Veränderungsvorschlag:
 char c;
 while ((c = pgm_read_byte(&z_string[0])) != '\0')
    {
      // aktuelles Datum aus String lesen, zum GLCD ausgeben
      // und danach den Zeiger auf den String inkrementieren
      glcd_write_byte ( c - 32 ,'D');
      z_string++;
    }

So (ähnlich) gehts bei mir ;-)

Autor: Michael J. (jogibaer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner B. wrote:
> Mehrere Probleme:
>
>  while (*z_string != 0)  <==== Funktioniert nicht!
>   steht ja im progmem. Zugriff nur über pgm_read_byte!
>
>     pgm_read_byte (z_string ++);   <=== Das ++ "geht so ab und zu
> nicht".
>

Hallo,

warum geht "while ..." nicht ?
Der Zeiger wird doch eigentlich im Ram angelegt und zeigt dann auf die
Programmspeicheradresse, oder ?


pgm_read_byte (z_string ++)

Warum geht das ab und zu nicht ?


Jogibär



Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der zeiger wird im while DEREFERENZIERT also auf den Inhalt zugegriffen. 
Das geht bei Zeigern in Progme nun einmal per pgm_read_byte/word/...

RAM     =>  c = *data;
PROGMEM =>  c = pgm_read_byte(data);
EEPRO   =>  c = eeprom_read_byte(data);

Siehe
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Warum geht das ab und zu nicht ?

Ich tippe darauf: Weil pgm_read_byte ein macro ist.

Autor: Michael J. (jogibaer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


>>>Der zeiger wird im while DEREFERENZIERT also auf den Inhalt zugegriffen.
>>>Das geht bei Zeigern in Progme nun einmal per pgm_read_byte/word/...

Wenn ich das richtig verstehe, zeigt der Zeiger ansonsten in den 
normalen
Ram Bereich.

Per  pgm_read_byte/word/... komme ich dann in den Flash.

Jogibär

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So isses!
Der Compiler/Prozessor weiss nicht wohin der Zeiger zeigt.
Einer Wert von 123 kann auf ein Speicherstelle im RAM, FLASH, oder ins 
EEPROM zeigen. Der Zeiger selbst ist immer 123 ohne Zusatzinformation. 
Den Speichertyp musst du (zumíndest bei AVR-GCC/WinAVR) dem Compiler 
mitteilen. Nachdem das Sternchen schon für RAM verbraten ist, haben sich 
die Jungs/Mädels die die AVR-LIBC gezaubert haben etwas anderes 
ausdenken müssen...

Werner

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.