www.mikrocontroller.net

Forum: Compiler & IDEs Pointer auf Strings im FLASH?


Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
vielleicht kann mir jemand bei folgendem Problem helfen. An meinen
ATMEGA 128 habe ich ein LCD-Display angeschlossen, und in C die
Funktion Send_Data_2_LCD(char*) geschrieben, die das senden von Daten
an das LCD erleichtern soll. Der Funktion wird beim Aufruf ein Pointer
mit uebergeben, welcher auf eine Adresse im FLASH zeigt, wo dann die
entsprechende Zeichenkette stehen soll.

Der folgende Code funktioniert aber leider nicht:

main()
{
  static char Zeichenkette1[] PROGMEM = "Hallo Welt";
  :
  :
  Send_Data_2_LCD(Zeichenkette1);
  :
  return;
}

void Send_Data_2_LCD(char* Pointer)
{
  char* temp = Pointer;
  do
  {
    SPDR = *temp;
    :
    :
    ++ temp;
  } while(!temp);
  return;
}

Irgendwie geht beim Funktionsaufruf die Information verloren, wo der
Pointer hinzeigen soll, -RAM oder FLASH-.

Hat jemand eine Idee, wie man das realisieren kann.


Gruesse AstroNookie

Autor: Danyo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich geb dir mal ne UART-Funktion:

const char pgmStartString[] PROGMEM = "ATmega32 online!";

int main (void)
{
   char cUseBuffer[30];

   UART_TxStr(strcpy_P(cUseBuffer, pgmStartString));
}

void UART_TxStr(unsigned char *p_pucString)
{
  while(*p_pucString!=0)
  {
     outp(*p_pucString, UDR);
     loop_until_bit_is_set(UCSRA, UDRE);
     p_pucString++;
  }
}

Kannst du dann für's LCD adaptieren.

Gruß Danyo

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Danyo,
vielen Dank fuer die schnelle Antwort. Wenn ich das richtig
interpretiere, dann kopierst Du zuerst den String ins RAM, und
uebergibst dann einen Pointer, der ins RAM zeigt.
Daran habe ich auch schon gedacht! :-)

Das ist sicherlich eine Moeglichkeit, wie man das eigentliche Problem
umgehen kann. Aber gibt es denn nicht eine Loesung, wie man den Pointer
der in das FLASH zeigt "richtig" uebergeben kann? Im Prinzip muesste
das was AVR-spezifisches sein, da ja der AVR eine Harvard-Architektur
hat, und die Daten vom Program-Code getrennt sind. Hmmmmmm???

Vielen Dank nochmals Danyo

Beste Gruesse
AstroNookie

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

Bewertung
0 lesenswert
nicht lesenswert
(Warum machst du gleich zwei Threads auf?)

Du müsstest eine putchar-Routine schreiben, die die Bytes
einzeln aus dem ROM holt und ausgibt.

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Joerg,
das mit den zwei Threads war keine Absicht, und da ich nicht weiss, wie
man einen Thread loeschen kann, gibt es nun dummerweise zwei Threads,
sorry. Falls es eine Moeglichkeit gibt den Thread zu loeschen, dann bin
ich ganz Ohr. :-)

Nochmal zum Thema, wie soll die routine putchar das Problem loesen? Was
ich moechte ist eine Funktion, der ich einen Pointer mit auf den Weg
gebe, der in das FLASH zeigt. Aber bislang habe ich so etwas noch nicht
gefunden.

Gruss
AstroNookie

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Komisch,
jetzt wurde die Antwort auf den letzten Beitrag schonwieder 2 mal
gesendet. Ich habe keine Ahnung woran das liegt???

Gruss
AstroNookie

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

Bewertung
0 lesenswert
nicht lesenswert
Machst du vielleicht Doppelklicks auf den Sende-Knopf?

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich klick nur einmal auf Submit!!!

Vielleicht prellt ja meine Maus ;-)    (Kleiner Scherz am Rande)

Gruss
AstroNookie

Autor: Danyo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst es von mir aus auch mit einem Pointer auf ein einzelnes
Zeichen machen, aber das wär mir zu umständlich...

const char pgmStartString[] PROGMEM = "ATmega32 online!";

for (int i=0; i<sizeof(pgmStartString); i++) {
      UART_TxChar(pgm_read_byte(&pgmStartString[i]));
}

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Danyo,
ja, das sieht etwas umstaendlich aus, sollte aber auch funktionieren.
Vielen Dank fuer deine echt hilfreichen Kommentare.

Gruesse zurueck
AstroNookie

Autor: Frank Wallenwein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Danyo,

prinzipiell ne gute Idee. Nur eins scheint mir hier nicht ganz zu
stimmen.

> const char pgmStartString[] PROGMEM = "ATmega32 online!";
> for (int i=0; i<sizeof(pgmStartString); i++) {


sizeof(pgmStartString) liefert Die die Länge des Pointers zurück.
Du brauchst aber die Stringlänge  -  also strlen()
Da strlen() aber nur im RAM geht, bräuchtest Du hier strlen_P()

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pgmStartString ist ein Array, kein Pointer, daher passt sizeof().

Autor: Frank Wallenwein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A.K. - Da hast Du recht !  - Sorry.
Frank

Autor: Volker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Stichwort pgm_read_byte

 void displayausg (const prog_char *txt)
  {
    //wenn Pointer auf Flash zeigt

      data2lcd (pgm_read_byte(txt));
  }

Volker

Autor: Astro Nookie (astronookie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle,
vielen Dank für eure zahlreichen Tipps. Die ideale Lösung hab ich jetzt
gefunden. Ich kopiere zuerst die Zeichenkette vom FLASH ins RAM, und
übergebe der Funktion einen Pointer, welcher ins RAM zeigt. Zudem habe
ich noch folgenden Define eingefuehrt, damit der Funktionsaufruf noch
etwas uebersichtlicher wird.
   :
   #define Send(x) (Send_String_2_LCD(strcpy_P(StringInRAM, (x))));
   :
Der Funktionsaufruf vereinfacht sich dann zu
   :
   Send(T_Init);
   :
mit T_Init gleich
   :
   char T_Init[] PROGMEM =  "Dieser Text steht im FLASH";
   :
Die eigentliche Funktion die aufgerufen wird, sieht dann so aus.
   :
   void Send_String_2_LCD(char* Pointer)
   {
  char* P_temp = Pointer;
  char temp;

  while(*P_temp != 0)
  {
    SPDR =  temp;
    do {} while(!(SPSR & (1<<SPIF)));
    ++P_temp;
  }
  return;
}

Die Variante, die Zeichenkette direkt ins RAM zu legen geht auch, aber
warume wertvollen RAM speicher verschwenden, wenn man einen 128KB
Speicher hat.

Viele Gruesse,
und Danke

AstroNookie

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.