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
> 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...
Vielleichts hilft's: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vereinfachung_f.C3.BCr_Zeichenketten_.28Strings.29_im_Flash 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. [...]
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
> Das PSTR(xxx) liefert mir ja einen Pointer auf den Text im Flash zurück, > oder irre ich mich da?
1 | #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__avr__pgmspace.html oder zu allen Funktionen/Deklarationen http://www.nongnu.org/avr-libc/user-manual/ inkl. FAQ, Beispiele, Doku.....
Achso, vielleicht hilft auch das GCC-Forum und Suche. klikk den mal vielleicht: http://www.mikrocontroller.net/search?query=PSTR&forums%5B%5D=2
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.
> 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.
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.