Forum: Compiler & IDEs Progmem mit Zeigern auf Funktionen


von Michael J. (jogibaer)


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

von Werner B. (Gast)


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:
1
 char c;
2
 while ((c = pgm_read_byte(&z_string[0])) != '\0')
3
    {
4
      // aktuelles Datum aus String lesen, zum GLCD ausgeben
5
      // und danach den Zeiger auf den String inkrementieren
6
      glcd_write_byte ( c - 32 ,'D');
7
      z_string++;
8
    }

So (ähnlich) gehts bei mir ;-)

von Michael J. (jogibaer)


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



von Werner B. (Gast)


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-Tutorial#Programmspeicher_.28Flash.29

von Werner B. (Gast)


Lesenswert?

> Warum geht das ab und zu nicht ?

Ich tippe darauf: Weil pgm_read_byte ein macro ist.

von Michael J. (jogibaer)


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

von Werner B. (Gast)


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

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.