www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Laufschrift auf dem HD44780


Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Paul Baumann (paul_baumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Paul Baumann (paul_baumann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!!!!
(",)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :.(

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kasperle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob Er weiß was ein Datenzeiger ist?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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
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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!!!!

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 (",)

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: lcd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hatte da auch mal was gemacht zu meinen Anfängen
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <string.h>

#include <lcd.h>

#define length 30
char sLauftext[length+1];

char* move_text_left(char* text, uint8_t len)
{
  char tmp = text[0];  
  uint8_t i;

  for( i = 0; i<len; i++)
  {
    text[i] = text[i+1];
  }
  text[len-1] = tmp;
  return text;
}


void wait (uint16_t zeit) //zeit: wartezeit in ms (0 bis 65536)
{
   uint16_t i;
   for(i=0;i<zeit;i++) _delay_ms(1); //da für _delay_ms max Takt-abhängige Werte erlaubt
} 

int main (void) 
{  
  char sLauftext[length+1];
  uint8_t n;

  lcd_init(LCD_DISP_ON);
  lcd_clrscr();
  strcpy(sLauftext,"Dies ist der Lauftext Test    ");
  lcd_puts(sLauftext);
  n=strlen(sLauftext);
  wait(1000);

while(1)
{ 
  lcd_clrscr();
  strcpy(sLauftext,move_text_left(sLauftext,n)); 
  lcd_puts(sLauftext);
  wait(200);
}

return 0;           
}

die ganzen lcd Funktionen tun ja hier nichts zur sache, geht ja nur um 
das shiften des Textes

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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

Autor: Stephan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marcel K,

kannst du dein Code posten? .c und .h Datei

Autor: Stephan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

hatte noch was vergessen:
Es musste noch die Pos bei jedem schreiben gesetzt werden.
Jetzt sollte alles klappen.

Stephan

Autor: Marcel K. (viewer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@: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

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Marcel,
habe ein bisschen gespielt aber irgendwie fuktioniert nicht! wie sieht 
deine main File aus?
Frank

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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ß

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

Bewertung
0 lesenswert
nicht lesenswert
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:
#include <avr/io.h>
#include <lcd.h>

#define CHARS_PER_LINE  16

void TextOut( const char* string )
{
  int nrChars = 0;
  
  lcd_gotoxy( 0, 0 );
  while( nrChars < CHARS_PER_LINE && *string ) {
    lcd_data( *string++ );
    nrChars++;
  }
    
  while( nrChars++ < CHARS_PER_LINE )   // am Ende mit Leerzeichen auffüllen, falls
    lcd_data( ' ' );                    // notwendig, weil der String schon
                                        // zu kurz ist
}

int main()
{
  const char * Text = "Juhu es ist bald wieder Fruehling";
  const char * TextTeil;
  
  lcd_init();
  
  while( 1 ) {
    TextTeil = Text;
    while( *TextTeil ) {
      TextOut( TextTeil );
      TextTeil++;
      _delay_ms( 200 );
    }
  }
}

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.
  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

Autor: Marcel K. (viewer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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

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.