www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Texte im SRAM, Überlauf??


Autor: Philipp Putzer (putzer_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich beschäftige mich seit geschlagenen 6 Stunden um das Fehlverhalten 
meines Programms auszumerzen.

Folgendes:
Ich will mit einem 4x20 LCD eine Menüstruktur aufbauen, so mit vier bis 
fünf Tasten zur Navigation (links, rechts, +, - MENÜ). So ein Menü habe 
ich schon öfters gemacht, bisher waren diese auch nicht gerade ewig lang 
und aufwendig.

Nur dieses Mal wird das Ganze etwas länger, wodurch ich auch mehr Texte 
usw. anzeigen und speichern muss.

Meine bisherige Idee war:
Ich schreibe den Menütext, wohin mein Menüpointer (diesen verändere ich 
mit den Tasten PLUS und MINUS) zeigt, mit einem Pfeil vorangestellt ans 
Display. Die restlichen Texte werden einfach umdrei Stellen nach rechts 
versetzt und ohne Pfeil ans LCD geschrieben.

In etwa so:

"-> Menüpunkt 1      "
"   Menüpunkt 2      "
"   Menüpunkt 3      "
"   Menüpunkt 4      "

Naja, eine etwas unelegante Methode, da ich bei einer Änderung immer den 
gesatem Bildschirm neu schreibe. Der Pfeil bewegt sich nur optisch auf 
und nieder, in Wahrheit wird der gesamte Bildschirminhalt neu aufgebaut. 
Würde ich den Pfeil mit den Stringfunktionen z.B. an den Text vorne 
herankopieren würde ich vielleicht 8 Texte weniger brauchen

Nun (endlich) zum Problem

Kurz: Die ganzen Texte scheinen irgendwie nicht im SRAM(?) platz zu 
haben.

Alles in allem habe ich ca. 50 Texte à 20 Zeichen => 1kByte Speicher im 
Flash.

Soweit ich das nun vertsanden habe, lädt das Programm zu Beginn die 
Texte in den SRAM, welcher dann überläuft, und das totale Kaos tritt 
auf.

Kann ich diese nicht auch vom Flash heraus ins LCD schreiben; oder 
zumidest  nur in den RAM laden wenn diese gerade benötigt werden?

Lösche ich mal die halben Texte für das Menü, funkt es perfekt.

Gibt es da irgendwas (programmtechnisches), wie ich mein Problem lösen 
könnte?? Vielleicht ohne den ganzen Menüaufbau über den Haufen zu 
werfen?

Achja, momentan "läuft" das Ganze auf einem ATMEGA16 mit 1kByte RAM


Vielen vielen Dank und schöne Grüße

philipp

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kurz: Die ganzen Texte scheinen irgendwie nicht im SRAM(?) platz zu
> haben.
>
> Alles in allem habe ich ca. 50 Texte à 20 Zeichen => 1kByte Speicher im
> Flash.
>
> Achja, momentan "läuft" das Ganze auf einem ATMEGA16 mit 1kByte RAM

1kByte(Texte) + Variablen + Stack = deutlich mehr als 1kByte
-> SRAM reicht nicht aus
-> Stack kollidiert mit Variablen / Texten.


> Soweit ich das nun vertsanden habe, lädt das Programm zu Beginn die
> Texte in den SRAM, welcher dann überläuft, und das totale Kaos tritt
> auf.

Richtig... siehe oben.


> Kann ich diese nicht auch vom Flash heraus ins LCD schreiben; oder
> zumidest  nur in den RAM laden wenn diese gerade benötigt werden?

Ja.


> Gibt es da irgendwas (programmtechnisches), wie ich mein Problem lösen
> könnte?? Vielleicht ohne den ganzen Menüaufbau über den Haufen zu
> werfen?

Ja. Das Thema wurde, wenn ich mich nicht irre, schon desöfteren hier im 
Forum behandelt...

Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleichts hilft's:

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

Vereinfachung für Zeichenketten (Strings) im Flash

Zeichenketten können innerhalb des Quellcodes als "Flash-Konstanten" 
ausgewiesen werden. Dazu dient das Makro PSTR aus pgmspace.h. Dies 
erspart die getrennte Deklaration mit PROGMEM-Attribut.

[...]

Autor: Philipp Putzer (putzer_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Aha, das klingt schon mal sehr gut!

Nur leider habe ich noch ein (verständniss-) Problem.

Ich habe nun alle Texte folgendermaßen deklariert:
unsigned char texte_ueberschrift_0 [] PROGMEM = "       Setup        ";

Weiter unten im Programm verwende ich den Text folgendermaßen:
lcd_writetext( PSTR(texte_ueberschrift_0) );

Die Funktion lcd_writetext sieht folgendermaßen aus:

void lcd_writetext ( char *text)
{ uint8_t i = 0;
  while (text[i]!=0)
  { lcd_writechar(text[i]);
    i++;
  }
}

Beim Compilieren erhalte ich die Fehlermeldung "invalid initializer" 
bzw. die Warnung "passing arg 1 of `lcd_writetext' discards qualifiers 
from pointer target type"

Mein Frage nun, muss ich bei der Deklaration PROGMEM hinzuschreiben oder 
nicht?

Das PSTR(xxx) liefert mir ja einen Pointer auf den Text im Flash zurück, 
oder irre ich mich da? Meine Lcd-Routine erwartet ja auch einen Pointer, 
demnach müsste das ja passen.

Lasse ich das PSTR weg, zeigt mir das LCD völlig zusammenhanglose Texte 
an.


Kann mir jemand sagen was ich da falsch mache??

Vielen Dank
Philipp

Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das PSTR(xxx) liefert mir ja einen Pointer auf den Text im Flash zurück,
> oder irre ich mich da?
#define PSTR (s)   ((const PROGMEM char *)(s))
Used to declare a static pointer to a string in program space.

Mehr dazu findest du hier:
http://www.nongnu.org/avr-libc/user-manual/group__...

oder zu allen Funktionen/Deklarationen
http://www.nongnu.org/avr-libc/user-manual/

inkl. FAQ, Beispiele, Doku.....

Autor: Hegy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, vielleicht hilft auch das GCC-Forum und Suche.
klikk den mal vielleicht:

http://www.mikrocontroller.net/search?query=PSTR&f...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Philipp Putzer wrote:
> Hi!
>
> Aha, das klingt schon mal sehr gut!
>
> Nur leider habe ich noch ein (verständniss-) Problem.
>
> Ich habe nun alle Texte folgendermaßen deklariert:
> unsigned char texte_ueberschrift_0 [] PROGMEM = "       Setup        ";
>
> Weiter unten im Programm verwende ich den Text folgendermaßen:
> lcd_writetext( PSTR(texte_ueberschrift_0) );
>

Wenn der Text mittels
 unsigned char texte_ueberschrift_0 [] PROGMEM = "       Setup        ";

sowieso schon im Flash liegt, dann brauchst du das PSTR
nicht mehr. Das PSTR ist nur ein Makro, dass dir erlaubt
Texte 'on the fly' in den Flash zu verlagern. Also
in Fällen wie

   lcd_writetext( PSTR( "Dies ist ein Text" ) );

Normalerweise würde "Dies ist ein Text" im SRAM landen und das
PSTR sorgt dafür, dass er ins Flash kommt.


> Die Funktion lcd_writetext sieht folgendermaßen aus:
>
> void lcd_writetext ( char *text)
> { uint8_t i = 0;
>   while (text[i]!=0)

Nein.
Schau noch mal ins Tutorial.
Wenn text ein Pointer in den Flash ist (und das muss er bei
dir jetzt sein), dann geht das nicht so, sondern mit der
Funktion pgm_read_byte. Im Tutorial ist doch eine Funktion
die Text aus dem Flash holt und die einzelnen Zeichen auf dem
UART ausgibt. Das 'auf dem UART ausgeben' ersetzt du durch
'auf dem LCD ausgeben' und du hast deine Funktion.

> Kann mir jemand sagen was ich da falsch mache??

Studiere das Tutorial noch mal.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In etwa so:
>
> "-> Menüpunkt 1      "
> "   Menüpunkt 2      "
> "   Menüpunkt 3      "
> "   Menüpunkt 4      "
>
> Naja, eine etwas unelegante Methode, da ich bei einer Änderung immer den
> gesatem Bildschirm neu schreibe. Der Pfeil bewegt sich nur optisch auf
> und nieder, in Wahrheit wird der gesamte Bildschirminhalt neu aufgebaut.
> Würde ich den Pfeil mit den Stringfunktionen z.B. an den Text vorne
> herankopieren würde ich vielleicht 8 Texte weniger brauchen

Sag blos, du hast jeden Text 2-mal: Einmal mit Pfeil und einmal
ohne Pfeil.

Wozu musst du den Bildschirm immer neu aufbauen?
Du kannst den Cursor positionieren.

Beim 'Cursor down'

 * Cursor in die Zeile wo der Pfeil jetzt ist, in Spalte 0
 * 3 Leerezeichen ausgeben
 * Cursor in die Zeile wo der Pfeil hin soll, in Spalte 0
 * "-> " ausgeben

fertig. Ausser im Fall das gescrollt werden muss, muss der Schirm
keineswegs neu aufgebaut werden.

Und wenn du die Menütexte beim ausgeben gleich ab Spalte 3 ausgibst,
dann kannst du dir auch die 3 Leerzeichen, mit denen jeder Menütext
anfängt sparen und sparst so gleich mal 50 * 3 = 150 Bytes ein.


Autor: Philipp Putzer (putzer_philipp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaubs ja fast nicht! Das ging ja schnell!!!

Jetzt verstehe ich auch den Unterschied zwischen PROGMEM und PSTR, super 
danke!

Nun funkt es tadellos!!

@ Karl heinz Buchegger

Ja, das war meist nur eine Notlösung; Aber bei so einem Haufen Texte 
werde ich es sicher anderst machen, wäre ja schade um den verbrauchten 
Speicher.


Also nochmal vielen Dank an alle!!

Schöne Grüße
Philipp

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich gebe zu, daß ich bei den Text-Displays auch nicht mit dem Cursor 
rumwerke.
Meine Variante: für jede Displayzeile ist passend Ram reseviert.
Vorgabetexte werden beim ersten "Bild-"Aufbau vom Flash ins Ram kopiert.
Innerhalb des Menüs/der Funktion weredn nur veränderte Zeichen in Ram 
geschrieben und dann die komplette Zeile ans Display geschickt.

Allerdings in Assembler, deshalb hier kein Beispiel. ;)

Eigentlich habe ich so nur eine "Copy"-Routine, die bekommt den 
Textzeiger und die Zeilennummer, die löscht die gewünschte Zeile im Ram 
und kopiert dann den Text aus dem Flash bis zum 0-Byte ins Ram.

Für das Display gibt es außer Init so nur "Write Line" mit der 
Zeilenummer, um die Zeile ins Display zu schaffen.

Bisher hat die unnötige CPU-Last noch nicht wirklich gestört und so ist 
es für kleinere Sachen schön übersichtlich.

Gruß aus Berlin
Michael

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.