Forum: Compiler & IDEs LCD funktioniert nicht


von Michael (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich bin gerade am Anfang des C Lernens und habe nun ein LCD an meinen 
Mega128 angeschlossen. Ich verwende die Headerdatei von Peter Fleury und 
ein Beispielprogramm von ihm. Doch am LCD wird nichts angezeigt. In 
einem C-Buch habe ich eine Logik gesehen, die zwischen Rd, Wr und E 
angeschlossen ist. Muss ich auch so eine Logik einbauen oder reicht es 
wenn ich das LCD direkt über 4 Bit mid dem Mega128 verbinde?
Der Compiler zeigt nur immer "undefined reference" an.

von Frank (Gast)


Lesenswert?

zum Glück gibts ja nur einen einzigen Typ LCD-Anzeigen auf diesem 
Planeten....

bye

Frank

von johnny.m (Gast)


Lesenswert?

Wenn der Compiler "undefined reference" anzeigt, dann ist das eine 
Fehlermeldung! D.h. das Programm wird gar nicht korrekt kompiliert, und 
das hat nichts mit irgendwelcher Logik zu tun. Wenn Du mal die komplette 
Fehlermeldung posten könntest, wäre das eine große Hilfe!

von Michael (Gast)


Lesenswert?

Ich habe ein 4x20 LCD das kommpatibel zum HD44780 ist. Ich habe nun im 
Forum gelesen dass ich die LCD.c und die testLCD.c einbinden muss. 
Dadurch sind auch die Fehler verschwunden. Doch das LCD zeigt immer noch 
nichts an. Ich habe das LCD an Porta und habe die LCD.h Datei so 
umgeänder. Die RW leitung habe ich auf GND ich hoffe dass dies so auch 
funktioniert.

von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?

>hoffe dass dies so auch funktioniert.

Hoffen und glauben kannst du in der Kirche!

Lesen solltest du das hier:
http://www.mikrocontroller.net/articles/AVR-Tutorial

und das Datenblatt deines Displays!

von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?


von Michael (Gast)


Lesenswert?

Nach dieser Anleitung bin ich vorgegangen. Doch in der LCD.h steht etwas 
von Port RW. Ich habe in C noch nicht so viel Ahnung. Deshalb kann ich 
mid den LCD und testLCD Datein noch nicht sehr viel anfangen. Aber mit 
irgendetwas muss man ja auch mal beginnen C zu lernen. Muss ich da noch 
etwas umstellen?

von Karl heinz B. (kbucheg)


Lesenswert?

> Doch das LCD zeigt immer noch nichts an.

Gar nichts?
   -> Kontrastspannung stimmt nicht oder Versorgungsspannung
      ist nicht angeschlossen

LCD zeigt in der 1. und 3. Zeile eine Reihe von 'Balken'
   -> Kontrastspannung stimmt und du hast ein Problem
      in der Initialisierung

Welches ist es nun?

von Michael (Gast)


Lesenswert?

Also es zeigt schon 2 Balken an in der 1. und 3. Zeile. das Display ist 
ein Powertip PC2004M-P2 von Pollin. Dieses läuft auch in Bascom 
einwandfrei.

von johnny.m (Gast)


Lesenswert?

Also was denn jetzt, Fehlermeldung oder nicht?

Ich habe mit der vielgerühmten Fleury-Lib noch nicht gearbeitet, meine 
mich aber erinnern zu können, dass man erstmal angeben muss, an welchen 
Pins das Display überhaupt angeschlossen ist, sonst schreiben die 
Funktionen ins Nirvana und am Display kommt nix an. Und diese Angaben 
sehe ich in Deinem Programm nicht.

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

dies steht ja in der h. Datei, an welche Pins dies angeschlossen ist. 
Ist dies Beispiel von Peter Fleury nicht so gut? gibts eventuell andere 
Beispiele die man besser verstehen kann.

von Michael (Gast)


Angehängte Dateien:

Lesenswert?

außerdem habe ich auch noch diese Datei.

von Michael (Gast)


Lesenswert?

Ich glaube es liegt am RW anschluss. ich habe gelesen, dass diese Lib 
die Busy-Kontrolle unterstützt. Ich probiere dies jetzt mal aus obes 
dann läuft. Doch ist es auch möglich dies ohne die RW leitung zum laufen 
zum bringen? Denn ich habe ein Board wo dieser Pin auf GND ist.

von Michael (Gast)


Lesenswert?

nun läuft das LCD. es lag doch an der RW-Leitung. Danke für eure Hilfe. 
Aber mich würde doch interresieren obs nicht doch ohne gehen würde?

von Karl heinz B. (kbucheg)


Lesenswert?

> ich habe gelesen, dass diese Lib
> die Busy-Kontrolle unterstützt.
> Denn ich habe ein Board wo dieser Pin auf GND ist.

Dann ist alles klar.
Die Fleury Lib braucht die RW Leitung. Die wartet
und wartet und wartet und wartet ... darauf das
das LCD mittels Busy Flag mitteilt, dass es bereit
ist wieder Daten anzunehmen.


von fieser Rahul (auch Oskar genannt) (Gast)


Lesenswert?

>Aber mich würde doch interresieren obs nicht doch ohne gehen würde?

Nennt sich die Leitung nicht "/RW"?
Ein "/" vor einem Buchstaben bedeutet in der Regel, dass die damit 
zusammenhängende Funktion bei L-Pegel aktiv ist.
Du versuchst also die ganze Zeit etwas in ein LCD zu schreiben, das gar 
nicht deine Daten haben will, sondern selber welche loswerden will.

von johnny.m (Gast)


Lesenswert?

@Rahul-Oskar:
Nö, die Leitung heißt R//W (der zweite "/" soll die Negation sein...) 
und kann, wenn kein Busy-Read gemacht werden soll, auf GND gelegt werden 
(also permanent Write).

von Karl heinz B. (kbucheg)


Lesenswert?

Michael wrote:
> nun läuft das LCD. es lag doch an der RW-Leitung. Danke für eure Hilfe.
> Aber mich würde doch interresieren obs nicht doch ohne gehen würde?

Klar. Würde auch gehen.
Im Fleury Code gibt es eine Funktion für das Abfragen
des Busy Flags. Die musst du umschreiben: Von 'Warten
auf das Busy Flag' zu 'Eine konstante Zeitdauer warten'


von Michael (Gast)


Lesenswert?

so nun habe ich in der "static uint8_t lcd_waitbusy(void)" nur noch 
_delay_ms(50); stehen. Bis jetzt funktionierts auch. Soweit ich den Code 
verstanden habe muss ich sonst nichts mehr umkstellen. wie weit kann ich 
denn mit dem delay runter gehnen. Hat das was mit der Datadelay time auf 
sich oder auf welche Zeit muss ich da schauen im Datenblatt?

von Karl heinz B. (kbucheg)


Lesenswert?

> Soweit ich den Code verstanden habe muss ich sonst nichts mehr
> umkstellen.

Richtig

> wie weit kann ich denn mit dem delay runter gehnen.

Probiers einfach aus. Ich würde mal schätzen, dass ein
Clear-Display am längsten dauert. Also ständig
Clear Display und einen Text hinten nach schicken.
Wenn der Text nicht mehr vollständig angezeigt wird,
dann wars zu kurz. Von der Zeitdauer dann noch
ein bischen was extra dazugeben (zur Sicherheit).


von Michael (Gast)


Lesenswert?

Danke für deine Antwort. In dieser Waitbusy Schleife wird aber auch noch 
der addresscounter abgefragt. Brauche ich den unbedingt? weil 
funktionieren tuts auch ohne?

von Michael (Gast)


Lesenswert?

nun habe ich noch eine letzte Frage. wie kann ich in die 3. und 4. Zeile 
schreiben? Das hat ja auch etwas mid dem Addresscouter zu tun.

von johnny.m (Gast)


Lesenswert?

Hast Du kein Datenblatt von dem Display? Da steht eigentlich immer drin, 
welche Stellen welche Adressen haben. Das ist z.T. auch 
herstellerabhängig. Bei den meisten 4-zeiligen Displays sind die 1. und 
3. Zeile eine logische Zeile und die 2. und 4. Zeile genauso. Wenn Du 
also die erste Zeile schreibst und dann am Ende weiterschreibst, müsste 
eigentlich in der 3. Zeile weitergeschrieben werden.

von Michael (Gast)


Lesenswert?

Das Datenblatt habe ich schon aber ich kann mit den Adressen nicht viel 
anfangen. Außerdem muss es doch auch eine andere Möglichkeit geben in 
die anderen Zeilen zu schreiben. Die Adressen stehen schon in der LCD.h 
drin.
/* put string to display (line 1) with linefeed */
        lcd_puts("LCD Test Line 1\n");

        /* cursor is now on second line, write second line */
        lcd_puts("Line 2");

warum ist dann Line 2 in der 2. Zeile?

von johnny.m (Gast)


Lesenswert?

Wenn die Fleury-Lib (mit der ich wie gesagt nicht arbeite, weil ich 
meine LCD-Routinen i.d.R. selber schreibe) das mit den Adressen alles 
schon drin hat, dann musst Du sicher irgendwo einstellen, dass Du ein 
4-zeiliges Display benutzt (wenn Du es noch nicht getan hast), denn die 
zeichnen sich wie gesagt meist dadurch aus, dass sie eigentlich (von der 
Adressierung her) nur zweizeilig sind. Die 4 Zeilen muss die Software 
bereitstellen.

von Michael (Gast)


Lesenswert?

eingestellt habe ich die 4 Zeilen in der LCD.h. Aber wie mache ich das 
dann wenn ich gleich in einer bestimmten Zeile beginnen will. im 
Beispiel steht nur  lcd_puts, dann schreibt er dies in die erste Zeile. 
Woher weis der Controller aber dass er dies in die 1. Zeile schreiben 
soll? Ich kapier nicht ganz wie der dann in die nächste Zeile springt.

von johnny.m (Gast)


Lesenswert?

Dann musst Du dem Display-Controller mit der entsprechenden Funktion 
mitteilen, an welche Adresse er das nächste Zeichen schreiben soll. Gibt 
es zu der Fleury-lib keine Dokumentation, in der das drinsteht? Sollte 
mich schwer wundern. Ich glaub, die Funktion, die Du brauchst heißt 
"lcd_gotoxy". Da kannst Du eine Zeilen- und Spaltennummer angeben.

Aber tu Dir einen Gefallen und lies Dir die Doku durch! Es ist nicht 
Sinn des Forums, hier den Leuten irgendwelche Informationen vorzubeten, 
die sie ohne viel Aufwand aus anderen Quellen viel schneller erhalten 
können. Und ich meine, mich erinnern zu können, des öfteren gelesen zu 
haben, dass die Fleury-lib recht gut dokumentiert sei.

von Michael (Gast)


Lesenswert?

Ich werde nochmal nach einer Doku suchen aber trotzdem danke.

von Karl heinz B. (kbucheg)


Lesenswert?

> /* put string to display (line 1) with linefeed */
>         lcd_puts("LCD Test Line 1\n");
>
>         /* cursor is now on second line, write second line */
>         lcd_puts("Line 2");
>
> warum ist dann Line 2 in der 2. Zeile?

weil hier

         lcd_puts("LCD Test Line 1\n");

                                  ^
                                  |

Ein Zeilenvorschub gemacht wird. Und wenn mich nicht alles
täuscht dann werte Peter Fleury dieses Zeichen '\n' auch
aus und setzt den Cursor in die nächste Zeile, so wie
es sein soll. Das Einzige was er noch nicht macht, ist
das Display scrollen, wenn man unten rauskommt. Frag
mich aber nicht was in diesem Fall passiert.

Ansonsten:
  lcd_gotoxy( Spalte, Zeile );

schickt den Cursor in eine bestimmte Zeile und dort
auf eine bestimmte Spalte.


Ich würde dir empfehlen, dass du mal in das lcd.h
hineinschaust. Dort sind unter anderem auch alle
Funktionen drinn (und auch kurz beschrieben) die
dir so zur Verfügung stehen. So wie es in C üblich ist.

Wenn du die Fleury Lib am laufen hast und auch alles
richtig eingestellt ist, kannst du das Datenblatt zum LCD
vergessen. Fast. Mit einer Ausnahme: Wenn du selbst Zeichen
definieren willst. Aber ansonsten brauchst du das Ding
nicht mehr. Und das ist auch gut, so denn das ist der Sinn
einer fertigen Library.


von Michael (Gast)


Lesenswert?

Bald kenn ich die Lib auswendig. Mit \n funktioniert dies auch wunderbar 
von der 1. auf die 2. Zeile. Doch auf die dritte springt er nicht. Ich 
nehme mir jetzt mal den addressCounter unter die Lupe.

von Michael (Gast)


Lesenswert?

Da hilft mir die ganze Doku nichts. Nun habe ichs doch nochmal mid der 
RW version ausprobiert und mit der klapt es auch einwandfrei. Das 
Programm benötigt den return address counter. Aber ich weis noch nicht 
wie ich das umschreiben kann, weil ich in der lcd_read Funktion nichts 
vom addressCounter finde.

von Michael (Gast)


Lesenswert?

kann mir hier keiner weiterhelfen. Irgendwie wird Pos oder 
addressCounter nach der 2. Zeile zurückgesetzt.

von Karl H. (kbuchegg)


Lesenswert?

> Aber ich weis noch nicht wie ich das umschreiben kann, weil ich
> in der lcd_read Funktion nichts vom addressCounter finde.

Ist doch nicht so schwer das zu finden.

Das hier ist die Busy Wait Funktion:
1
static uint8_t lcd_waitbusy(void)
2
3
{
4
    register uint8_t c;
5
    
6
    /* wait until busy flag is cleared */
7
    while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}
8
    
9
    /* the address counter is updated 4us after the busy flag is cleared */
10
    delay(2);
11
12
    /* now read the address counter */
13
    return (lcd_read(0));  // return address counter
14
    
15
}/* lcd_waitbusy */

Die liest vom LCD aus, wo sich zur Zeit der Cursor befindet
und retourniert das Ergebnis.
Daher müssen wir weiter suchen, wo lcd_waitbusy benutzt
wird. Irgendwo wird es einen Aufruf der Funktion geben,
bei dem der Returnwert auch benutzt wird.

Aha. Es gibt insgesamt zwei Stück davon. Hier sind sie
1
int lcd_getxy(void)
2
{
3
    return lcd_waitbusy();
4
}

Den verfolgen wir etwas später weiter, was es mit diesem
Aufruf auf sich hat. Interessanter ist der 2.te
1
void lcd_putc(char c)
2
{
3
    uint8_t pos;
4
5
6
    pos = lcd_waitbusy();   // read busy-flag and address counter
7
    if (c=='\n')
8
    {
9
        lcd_newline(pos);
10
    }
11
    else
12
    {
13
#if LCD_WRAP_LINES==1
14
  ...

Da hebn wirs doch schon. Die Cursorposition vom lcd_waitbusy()
wird in pos gespeichert. Wenn das nächste auszugebende Zeichen
ein '\n' ist, dann wird die Funktion lcd_newline mit eben dieser
Cursorposition aufgerufen.

Was passiert in lcd_newline() ?
1
/*************************************************************************
2
Move cursor to the start of next line or to the first line if the cursor 
3
is already on the last line.
4
*************************************************************************/
5
static inline void lcd_newline(uint8_t pos)
6
{
7
    register uint8_t addressCounter;
8
9
10
#if LCD_LINES==1
11
    addressCounter = 0;
12
#endif
13
#if LCD_LINES==2
14
    if ( pos < (LCD_START_LINE2) )
15
        addressCounter = LCD_START_LINE2;
16
    else
17
        addressCounter = LCD_START_LINE1;
18
#endif
19
#if LCD_LINES==4
20
#if KS0073_4LINES_MODE
21
    if ( pos < LCD_START_LINE2 )
22
        addressCounter = LCD_START_LINE2;
23
    else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) )
24
        addressCounter = LCD_START_LINE3;
25
    else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) )
26
        addressCounter = LCD_START_LINE4;
27
    else 
28
        addressCounter = LCD_START_LINE1;
29
#else
30
    if ( pos < LCD_START_LINE3 )
31
        addressCounter = LCD_START_LINE2;
32
    else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )
33
        addressCounter = LCD_START_LINE3;
34
    else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )
35
        addressCounter = LCD_START_LINE4;
36
    else 
37
        addressCounter = LCD_START_LINE1;
38
#endif
39
#endif
40
    lcd_command((1<<LCD_DDRAM)+addressCounter);
41
42
}/* lcd_newline */

Der einlietende Kommentar sagt eigentlich schon alles:
Der Cursor wird an den Anfang der nächsten Zeile bewegt
bzw. zur ersten Zeile, wenn er ganz unten war.
Und genau das macht dann auch der Code.

Soweit zur Analyse des bestehenden. Die Frage die sich
jetzt stellt lautet: Wenn du vom Display nicht lesen
kannst, kannst du logischerweise auch nicht feststellen
wo am LCD der Cursor tatsächlich ist. Welche Möglichkeiten
hast du statt dessen
* Du verzichtest auf das Weiterschalten mittels '\n'.
  Ist kein Beinbruch. Es gibt ja immer noch die Möglichkeit
  mittels gotoxy den Cursor direkt zu positionieren
* Du benutzt wieder die RW Leitung
* Du führst selbst Buch darüber wo den der Cursor am LCD sein
  müsste und benutzt dies anstelle der Abfrage des LCD. Dazu musst
  du natürlich in allen Funktionen die die Cursorposition
  verändern eingreifen und dasselbe was das Display mit
  seinem Cursor macht auch in deiner Variable nachziehen.
  Ist zwar etwas Aufwand, würde aber gehen. Zumindest solange
  bis der erste Schlauberger das LCD unter Umgehung deiner
  angepassten Library auf das Display zugreift.


von Michael (Gast)


Lesenswert?

Danke für deine Mühe. Ich werde dies ausprobieren. Doch ist es glaub ich 
schlauer wenn ich einfach die RW Leitung auf meinem Layout noch 
hinzufüge.

von Anfänger (Gast)


Lesenswert?

Hallo

Bin seit ein paar Wochen mit dem gleichen Problem beschäftigt. Also 
meine LCD ist im 4 bit modus ohne den Busy auszulesen. Bei mit besteht 
nicht die Möglichkeit das umzuändern deshalb währe meine Frage ob du 
(Michael) dein angepasstes Programm hier rein setzen kannst.

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
Noch kein Account? Hier anmelden.