Hallo liebes Forum, ich möchte gerne mit einem HD44780- Display (2x16) einen Lauftext erstellen. Leider komme ich nicht weiter :o( Ich habe einen Text mit 38 Zeichen. Ich habe eine Funktion (in C) die schreibt diesen Text auf die 2. Zeile des Displays. Das ganze mach ich mit dem Befehl "Display- Shift" (positioniere zuerst an [15/2]). Das ganze funktioniert auch so lange bis das 26. Zeichen kommt. Dann wird der nachfolgende Text in die 1. Zeile weiter geschrieben. Naja mir ist ja schon klar dass irgendwann die DDRAM- Adresse komplett durchgeschoben ist und deshalb wird einfach ab den 26. Zeichen in der 1. Zeile begonnen. Jetzt ist aber meine Frage, kann ich die Adresse irgendwie zurücksetzen auch ohne dass der Text gelöscht wird? Ich habe es schon über "LCD-RESET" und "LCD-HOME" probiert, allerdings wird das Display natürlich gelöscht und ich müsste die letzten 16 Zeichen noch mal auf das Display schreiben. Das ist nicht wirklich toll. Hat jemand hier schon mal ein Lauftext auf diesem Display realisiert? Ich bin über jede Hilfe Dankbar. Viele Grüße und euch im Forum einen schönen Abend, Marcel
Guck mal hierhin: http://www.sprut.de/electronic/lcd/index.htm Dort findet man sehr gut erläutert, wie die RAM-Aufteilung aussieht, damit man die richtige Zeile erwischt. MfG Paul
Hallo Paul, vielen Dank für den Link, den habe ich allerdings vorhin schon mal "gefunden" als ich nach einer Lösung gesucht habe. Dieser Link hilft mir allerdings nicht wirklich weiter da ich ja nicht weiß wie ich vorgen soll, wenn bei meinem Beispiel in die 1. Zeile geschrieben wird. Ich habe ja das Datenblatt und darin steht bereits dass die 1. Zeile bei 0x00 und die 2. bei 0x40 beginnt. Ich wollte wissen ob es eine Möglichkeit gibt, die Adressen wieder zurückzusetzen ohne das der Inhalt auf dem Display gelöscht wird. Aber trotzdem danke für deine schnelle Antwort. Gruß Marcel
Du könntest den ganzen Text eventuell im RAM des Kontrollers halten, dortdrin "zurechtmachen" und dann das Ganze auf einen Schlag zum Display rüberschicken. Wie das in "C" geht, weiß ich aber nicht, -diese Sprache ist mir zu kryptisch, um sie zu lernen. ;-) MfG Paul
Hmm, ich denke das wird schwierig! Ich möchte einen Lauftext mit über 300 Zeichen laufen lassen. Das passt bestimmt nicht in seinem RAM rein ;o) Naja, aber trotzdem Danke!!!! (",)
@ Marcel K. (viewer) >allerdings nicht wirklich weiter da ich ja nicht weiß wie ich vorgen >soll, wenn bei meinem Beispiel in die 1. Zeile geschrieben wird. Ich >Möglichkeit gibt, die Adressen wieder zurückzusetzen ohne das der Inhalt >auf dem Display gelöscht wird. Vergiss die Scrollfunktion im LCD, die hat viel zu enge Grenzen. Mach es selber per Controller. ISt auch einfach. DDRAM Adresse auf 0x00 setzen 8 Zeichen schreiben DDRAM Adresse auf 0x40 setzen 8 Zeichen schreiben Datenzeiger im Controller um ein Zeichen weiter setzen Ein paar Dutzend Millisekunden Warten Das Ganze von vorn Das "Warten" macht man sinnvollerweise mit einem Timer-Interrupt MFG Falk
Hallo Falk, danke für deinen Vorschlag. Das hat aber nichts mit einer Laufschrift zu tun. Bei eine Laufschrift müsste das erste Zeichen z.b. an (15/1) geschrieben werden. Dann beim nächsten mal das erste Zeichen an (14/1) und das zweite an (15/1) beim nächsten schreiben das erste Zeichen an (13/1), das zwiete an (14/1) und das dritte an (15/1) uns so weiter... Wenn ich es so mache wie du es geschrieben hast wäre es ein ganz normaler Schreibvorgang. Grüße Marcel
@Marcel K. (viewer) >Wenn ich es so mache wie du es geschrieben hast wäre es ein ganz >normaler Schreibvorgang. Lesen bildet. "Datenzeiger im Controller um ein Zeichen weiter setzen" MfG Falk
Hääää, sorry ich hab es anscheinend wirklich nicht "geschnallt" !!!!!!! :o( Wie meinst du das?? Also ich setzte den cursor an (0/0) (das ist ja die Adresse 0, oder?) Dann soll ich 8 Zeichen schreiben. Wiso 8 Zeichen? Falk, es tut mir echt leid aber ich weis echt nicht wie du das meinst. Ich sehe bestimmt vor lauter Bäumen den Wald nicht mehr. Könnstest du mir etwas auf die Sprünge helfen? Ich wäre über jede Hilfe sehr dankbar!! Grüßer Marcel :.(
Hi Bin zwar nicht Falk. Aber was er meint: -Zeiger auf 1.Buchstaben im Text. Eine komplette Zeile ausgeben. -Kurz warten -Zeiger auf 2.Buchstaben im Text. Eine komplette Zeile ausgeben. -Kurz warten -Zeiger auf 3.Buchstaben im Text. Eine komplette Zeile ausgeben. .... MfG Spess
@ Marcel K. (viewer) >Also ich setzte den cursor an (0/0) (das ist ja die Adresse 0, oder?) Ja. >Dann soll ich 8 Zeichen schreiben. Wiso 8 Zeichen? Ahhh, das war ein unbewusster halber Denkfehler. Viele 1x16 LCDs werden als 2x8 adressiert. Da muss man das so machen. Bei deinem 2x16 muss man das nicht. Der Rest ist aber identisch. Im Prinzip ist es einfach. Du willst einen String ala
1 | char mein_text[38]"Hallo ich bin eine Laufschrift"; |
als Laufschrift in die 2. Zeile des LCD bringen. Also musst du beim ersten mal die Zeichen 0..15 ausgeben, dann 1..16, 2..17 etc. Das kann man wie bereits beschrieben in einer Schleife machen, welche den Index des ersten Zeichens immer hochzählt. Dann halt bei dir 16 Zeichen ausgeben, warten, wieder von vorn. Knifflig wird es nur ein wenig, wenn das Ende erreicht wird. Will man dann wieder von vorn anfangen, gibt es zwei Möglichkeiten. 1.) Man macht den String um soviele Zeichen länger, wie das LCD breit ist. Dann kopiert man einmalig die ersten X Zeichen ans Ende, dazu bietet C fertige Funktionen. Bei dir hätte dein Sting dann 38+16=54 Zeichen. Dann lässt man in oben genannter Schleife den Index von 0..37 laufen, die Anzeige ist immer OK. Wenn sie dann auf 0 zurück springt, gibt es einen nahtlosen Übergang. 2.) Man lässt den String wie er ist und prüft bei jedem Zeichen, welches, man ausgibt, ob der Index grösser als das zulässige Maximum von hier im Beispiel 37 ist. Wenn nein, gibt man das Zeichen aus, wenn ja, muss man vorher 37 abziehen, um den richtigen Index zu berechnen. Kann man auch per MODULO Operation. die zweite Methode spart etwas Speicher für die Daten, braucht dafür etwas mehr Rechenzeit. MFG Falk
Hallo Spess, ich habe es immer noch nicht verstanden, SORRY!!! Mich würde als erstens interssieren wieso 8 Zeichen. Sind da eventuell 16 Zeichen gemeint da es sich ja um ein 2x16 Display handelt. als zweitens verstehe ich nicht wieso ich nach dem ich an die 1. Zeile geschrieben habe (Adresse 0x00) dann als nächstes in die 2. Zeile (Adresse 0x40) schreiben soll? Nach deinem Verfahren: Wenn ich einen Zeiger auf meinen ersten Buchstaben mache, wo soll diese denn dann geschrieben werden? Und dann wohin soll der 2. Buchstaben- Zeiger zeigen? Sorry für das Fragen aber ich stehe echt auf'm Schlauch!!!!
Hallo Falk, ich war zu langsam!!! Ich habe's jetzt!!!! Ich werde es ausprobieren!! Danke erstmal und ich meld mich... Schönen Abend noch!!! Marcel (",)
Hallo Falk, (und auch Spess) Ich wollte Dir noch mal Bescheid geben wie das ganze bei mir ausgegangen ist. Ich habe nach deinem Vorschlag vorgestern bis gestern in den frühern Morgen "geproggt". Ich habe es mit Deiner Hilfe hinbekommen, Vielen Dank. Ich bin mir sicher dass jemand mit etwas mehr Erfahrung das ganze etwas komfortabler hin bekommen würde, vielleicht hast du eine "Code-optimiertere" Lösung. (Mehr mit Zeiger arbeiten) Auf jeden Fall hier mal ein Ausschnitt meines Codes. (Die .c und .h Datei sind hier jetzt nicht getrennt) #define ZEILENLAENGE 16 char displayzeile[ZEILENLAENGE]; // mit dieser Funktion wird die Displayzeile mit "Leerzeichen" gefüllt void reset_zeile(void) { char i; for(i=0; i<ZEILENLAENGE; i++) { displayzeile[i] = 0x20; } } // Diese Funktion zählt die Anzahl der Zeichen die in einem String enthalten sind char strleng(char *s) { char n; for (n=0; *s != '\0'; s++) { n++; } return n; } void laufschrift(char zeile, char *text) { char zahl; signed char i; // muss signed sein, da man in der for- Schleife bis auf 0 runter muss char n =0; // Variable die das aktuelle Zeichen in die Variable "displayzeile" schreibt char j; reset_zeile(); zahl = strleng(text); // Anzahl der zu übertragenden Zeichen for(i=zahl; i>0; i--) { set_cursor(0,zeile); // in dieser Schleife werden die Elemente im Array von hinten nach vorne geschoben. // Hierbei bekommt das [n-te] Element den Wert vom folgenden [n+1] Element. for(j=0; j<ZEILENLAENGE; j++) { displayzeile[j] = displayzeile[j+1]; } displayzeile[ZEILENLAENGE-1] = *(text+n); // Das letzte Element bekommt das nächste Zeichen des übergebenem Text lcd_string(displayzeile); n++; // erhöhen um das nächste Zeichen zu schreiben delay_ms(200); } // jetzt ist der komplette Text durchgelaufen. Jetzt muss der rest mit // Leerzeichen aufgefüllt werden. for(i=ZEILENLAENGE; i>0; i--) { set_cursor(0,zeile); for(j=0; j<ZEILENLAENGE; j++) { displayzeile[j] = displayzeile[j+1]; } displayzeile[ZEILENLAENGE-1] = ' '; lcd_string(displayzeile); delay_ms(200); } } Also noch mal vielen Dank für Deine/Eure Hilfe. Hat mir wirklich sehr geholfen. Grüße, Marcel
hatte da auch mal was gemacht zu meinen Anfängen
1 | #include <avr/io.h> |
2 | #include <stdlib.h> |
3 | #include <util/delay.h> |
4 | #include <string.h> |
5 | |
6 | #include <lcd.h> |
7 | |
8 | #define length 30
|
9 | char sLauftext[length+1]; |
10 | |
11 | char* move_text_left(char* text, uint8_t len) |
12 | {
|
13 | char tmp = text[0]; |
14 | uint8_t i; |
15 | |
16 | for( i = 0; i<len; i++) |
17 | {
|
18 | text[i] = text[i+1]; |
19 | }
|
20 | text[len-1] = tmp; |
21 | return text; |
22 | }
|
23 | |
24 | |
25 | void wait (uint16_t zeit) //zeit: wartezeit in ms (0 bis 65536) |
26 | {
|
27 | uint16_t i; |
28 | for(i=0;i<zeit;i++) _delay_ms(1); //da für _delay_ms max Takt-abhängige Werte erlaubt |
29 | }
|
30 | |
31 | int main (void) |
32 | {
|
33 | char sLauftext[length+1]; |
34 | uint8_t n; |
35 | |
36 | lcd_init(LCD_DISP_ON); |
37 | lcd_clrscr(); |
38 | strcpy(sLauftext,"Dies ist der Lauftext Test "); |
39 | lcd_puts(sLauftext); |
40 | n=strlen(sLauftext); |
41 | wait(1000); |
42 | |
43 | while(1) |
44 | {
|
45 | lcd_clrscr(); |
46 | strcpy(sLauftext,move_text_left(sLauftext,n)); |
47 | lcd_puts(sLauftext); |
48 | wait(200); |
49 | }
|
50 | |
51 | return 0; |
52 | }
|
die ganzen lcd Funktionen tun ja hier nichts zur sache, geht ja nur um das shiften des Textes
@ Marcel K. (viewer) Längere Quelltexte bitte als Anhang. >Vielen Dank. Ich bin mir sicher dass jemand mit etwas mehr Erfahrung das >ganze etwas komfortabler hin bekommen würde, vielleicht hast du eine >"Code-optimiertere" Lösung. Ja, Warum in aller Welt verschiebst du den Text im RAM? Man muss ihn nur immer mit neuer Anfangsadresse auslesen. MfG Falk
Hi, also das mit dem Kopieren der zeichen kostet zuviel Zeit! Im Anhang mal eine Version mit einem Pointer. Die "Init..." wird einmal aufgerufen, bzw wenn du den Text ändern willst. Die Funktion "Write.." rufst du dann zyklisch auf. mfg Stephan
Hi, hatte noch was vergessen: Es musste noch die Pos bei jedem schreiben gesetzt werden. Jetzt sollte alles klappen. Stephan
@:Frank Also ich habe Dir mal die zwei Dateien angehängt. Allerdings habe ich den Quellcode auch nur aus dem Tutorial hier im Forum. Ich habe nur die Delayfunktion mit in den Code mit reingepackt. Der Inhalt der Dateien ist auch nicht aufgeräumt und richtig dokumentiert. Ich komme dieses Wochenende auch nicht mehr dazu aber ich möchte unbedingt die hier neu erwähnten Vorschläge ausprobieren. Ich weiß also nicht ob es sich lohnt diese zwei Dateien zu verwenden. @ Falk: Du hast geschrieben: Ja, Warum in aller Welt verschiebst du den Text im RAM? Man muss ihn nur immer mit neuer Anfangsadresse auslesen. Ich bin mir nicht ganz sicher wie du das meinst. Meinst du ich soll den Text, so wie ich ihn in meiner Funktion "laufschrift()" übergeben bekomme, direkt an das Display senden ohne ihn in das Array "displayzeile" zu schreiben?? @ Stephan: Danke für deinen "Codeschnipsel" den werde ich ausprobieren so bald ich wieder die Gelegenheit dazu habe!!! Danke!! Also allen ein schönes Wochenende und viele Grüße, Marcel
Hallo Marcel, habe ein bisschen gespielt aber irgendwie fuktioniert nicht! wie sieht deine main File aus? Frank
Hallo Frank, ich bin noch nicht dazu gekommen. Wird heute bestimmt auch nichts mehr. In der Main steht auch nur "lcd_init(); Was du aber beachten musst, ist dass die Taktfrequenz in der "lcd_hd44780.h" bei "#define XTAL 4000000" richtig eingestellt ist. Ich habe in diesem Fall 4MHz. Vielleicht ist das ja schon das Problem! Grüße, Marcel
Hi Marcel vielen Dank, ok das mit dem lcd_init(); ist klar! aber Datei "lcd_hd44780.h" habe ich nicht, ist aus dem Tutorial? oder wo finde ich es? Gruß
Marcel K. schrieb: >> Ja, Warum in aller Welt verschiebst du den Text im RAM? Man muss ihn nur >> immer mit neuer Anfangsadresse auslesen. > > Ich bin mir nicht ganz sicher wie du das meinst. Meinst du ich soll den > Text, so wie ich ihn in meiner Funktion "laufschrift()" übergeben > bekomme, direkt an das Display senden ohne ihn in das Array > "displayzeile" zu schreiben?? studiere das mal:
1 | #include <avr/io.h> |
2 | #include <lcd.h> |
3 | |
4 | #define CHARS_PER_LINE 16
|
5 | |
6 | void TextOut( const char* string ) |
7 | {
|
8 | int nrChars = 0; |
9 | |
10 | lcd_gotoxy( 0, 0 ); |
11 | while( nrChars < CHARS_PER_LINE && *string ) { |
12 | lcd_data( *string++ ); |
13 | nrChars++; |
14 | }
|
15 | |
16 | while( nrChars++ < CHARS_PER_LINE ) // am Ende mit Leerzeichen auffüllen, falls |
17 | lcd_data( ' ' ); // notwendig, weil der String schon |
18 | // zu kurz ist
|
19 | }
|
20 | |
21 | int main() |
22 | {
|
23 | const char * Text = "Juhu es ist bald wieder Fruehling"; |
24 | const char * TextTeil; |
25 | |
26 | lcd_init(); |
27 | |
28 | while( 1 ) { |
29 | TextTeil = Text; |
30 | while( *TextTeil ) { |
31 | TextOut( TextTeil ); |
32 | TextTeil++; |
33 | _delay_ms( 200 ); |
34 | }
|
35 | }
|
36 | }
|
Es gibt keinen Grund da grossartige Texte in der Gegend rumzukopieren. Es genügt völlig, wenn du der Ausgabefunktion immer nur einen veränderten Startpunkt des Textes übergibst. Die Laufschrift entsteht aus dem Zusammenspiel der inneren while Schleife in main() und der speziellen Ausgabefunktion, die ab einer gewissen Startposition im Text eine entsprechende Anzahl an Zeichen ausgibt. Man könnte sich jetzt auch noch weiter spielen und dafür sorgen, dass der Text auch noch vom rechten Rand hereinscrollt. Am einfachsten ist das aber erreicht, indem man im Text einfach eine entsprechende Anzahl an Leerzeichen vorsieht.
1 | const char * Text = " Juhu es ist bald wieder Fruehling"; |
lcd_gotoxy ist die Funktion, die den Ausgabecursor an eine bestimmte Position setzt. lcd_data ist die Funktion, die ein einzelnes Zeichen ans LCD ausgibt. lcd_init sollte selbsterklärend sein
@ Frank: Ich habe dir leider die falschen Dateien geschickt. Ich habe hier bereits versucht die richtigen Dateien hochzuladen allerdings geht das im Moment nicht, keine Ahnung wieso. Teil mir einfach deine E-Mailadresse mit und dann kann ich dir die zwei Dateien schicken. (Oder du schickst mit als registrierter User hier im Forum eine Nachricht, das ist sicherer....) @Karl Heinz: Vielen Dank für deine Antwort, ich werde dies auf jeden Fall ausprobieren sobald ich die Zeit dafür finde, DANKE!!! Viele Grüße, Marcel
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.