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.
zum Glück gibts ja nur einen einzigen Typ LCD-Anzeigen auf diesem Planeten.... bye Frank
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!
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.
>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!
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?
> 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?
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.
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.
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.
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.
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?
> 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.
>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.
@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).
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'
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?
> 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).
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?
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.
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.
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?
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.
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.
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.
> /* 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.
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.
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.
kann mir hier keiner weiterhelfen. Irgendwie wird Pos oder addressCounter nach der 2. Zeile zurückgesetzt.
> 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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.