Hallo, ich möchte gerne mit der Include Datei von Blafusel (im Anhang) ein 16x2 HD44780 LCD-Display ansteuern. Das Display ist von Pollin: http://www.pollin.de/shop/dt/ODc1OTc4OTk-/Bauelemente_Bauteile/Aktive_Bauelemente/Displays/LCD_Modul_TC1602A_08.html Angeschlossen ist alles so wie es in der Routine drinnen steht. Aber ich bekomme nur wirre Zeichen (Siehe Bild nächster Post). Kann mir einer sagen was ich da ändern muss? Versuche das ganze schon seit Tagen zum laufen zu bekommen. LG
Das sieht doch schon viel besser als bei den meisten Leuten, die mit LCD scheitern. Aber nur aus der Headerdatei hast du kein laufendes Programm herausbekommen, oder?
Nein natürlich nicht ;-) Im Anhang ist die LCD-Test Datei von Blafusel. Mein Display ist 2x16, seins 2x24. Das sollte aber doch kein Problem sein oder? Solang ich in der LCD.c nicht über die 16´te Stelle hinaus komme.
Mir kommt so auf Anhieb die lcd_ini seltsam vor:
1 | lcd_write(0x38,0); // B 0010 1000 => 8-Bit-Modus aktivieren |
2 | lcd_write(0x2,0); // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten |
1. Es steht im Datenblatt und bei der Pollin Beschreibung nur "Industriestandard" aber nicht welcher Controller konkret drin ist. D.h. für mich, dass vorsichtshalber die vollständige HD44780 Initialisierung notwendig ist. Es fehlt also ein Teil der üblichen 3 Function-Set Aufrufe mit den notwendigen Delays dazwischen. 2. lcd_write schickt zwei Halbbytes hintereinander. Im ersten Teil der Intialisierung darf für die Function-Sets NUR das obere Halbbyte gesendet werden. 3. das zusätzlich lcd_flash_e schickt das letzte untere Halbbyte nochmal zum Controller. Das klappt hier garantiert nicht so wie erwartet. Mir kommt es so vor, als ob der ursprüngliche Code für einen 8-Bit Anschluss und für irgendeinen KS-Controller gedacht war. Da mag das so funktioniert haben. Mal so direkt im Forum zusammengetippt: Probier mal
1 | void lcd_write_init(uint8_t data) |
2 | {
|
3 | PORTC = (data>>4); // output high nibble only,(!) zzgl. Zustand für RS-Leitung |
4 | lcd_flash_e (); |
5 | }
|
6 | |
7 | ....
|
8 | // in lcd_init
|
9 | delay(16000); // 10ms warten bis LCD wirklich bereit (max. Wert lt. Datenblatt) |
10 | |
11 | lcd_write_init(0x30); // init 1 |
12 | delay(4100); |
13 | lcd_write_init(0x30); // init 2 |
14 | delay(100); |
15 | lcd_write_init(0x30); // init 3 |
16 | delay(100); |
17 | |
18 | lcd_write_init(0x20,0); // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten |
19 | |
20 | // das lcd_flash_e muss hier garantiert raus.
|
21 | |
22 | delay(100); // sicherheitshalber warten |
23 | |
24 | // ab jetzt 4-Bit-Modus
|
25 | ....
|
Das lässt sich zwar in weniger Taktzyklen erledigen, aber ich habe das Gefühl, dass im Moment Klarheit mehr gefragt ist :-)
Vielleicht macht es auch Sinn, mit etwas zu starten, das besser dokumentiert und wartbar ist. Dafür ist dein lcd_tools.h vielleicht die falsche Wahl. Die meisten kommen wohl damit halbwegs zurecht: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
A.H. schrieb: > lcd_write_init(0x20,0); // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten Dabei bekomm ich einen Fehler: Zu viele Argumente! Habe das ",0" mal rausgelöscht. Code ist jetzt: /* LCD Include-Datei * * Das LCD ist folgendermaßen angeschlossen: * PC4 = RS * PC5 = Enable * PC0-PC3 = D4-D7 * R/W ist n.c. * * 03/2005 Florian Schäffer, http://www.blafusel.de * */ #include <avr/io.h> #include <avr/delay.h> #define delay(us) _delay_loop_2 (((F_CPU/4000)*us)/1000) // wartet µs void lcd_write_init(uint8_t data) { PORTC = (data>>4); // output high nibble only,(!) zzgl. Zustand für RS-Leitung lcd_flash_e (); } // Enable-Leitung toggeln void lcd_flash_e () { PORTC = PORTC | ( 1<<DDC5 ) ; // Enable = HIGH delay(1); // kurz warten, damit Flanke entsteht PORTC = PORTC & ~( 1<<DDC5 ) ; // Enable = LOW delay(64); // Warten, bis der durch Enable angelegte Befehl hoffentlich verarbeitet wurde } // Kommando oder Zeichen an Display senden: rs=0 => Kommando, rs=1 => Zeichen void lcd_write (uint8_t data, uint8_t rs) { uint8_t dataBits ; if (rs) // write data (RS=1, RW=0) dataBits=0x10; // RS liegt an Pin 4 = B 0001 0000 = H 10 else // write instruction (RS=0, RW=0) dataBits=0; PORTC = dataBits |(data>>4); // output high nibble first, zzgl. Zustand für RS-Leitung lcd_flash_e (); PORTC = dataBits | (data&0x0F); // output low nibble, zzgl. RS-Leitung lcd_flash_e (); delay(2000); } // Display loeschen void lcd_cls () { lcd_write(0x02,0); // B 0000 0010 => Display loeschen delay(2000); // dauert eine Weile, Wert ausprobiert lcd_write(0x01,0); // B 0000 0001 => Cursor Home delay(2000); // dauert eine Weile, Wert ausprobiert } // Zeichenausgabe void lcd_writechar (uint8_t zeichen) { lcd_write (zeichen, 1); } // gibt eine Zeichenkette auf dem LCD aus void lcd_writetext ( char *text) { uint8_t i = 0; while (text[i]!=0) { lcd_writechar(text[i]); i++; } } // gibt eine int-Zahl auf dem Display aus. Zweiter Parameter = Anzahl der Stellen (führende Leerzeichen), // space=0 => führende Nullen, 1 => führende Leerzeichen void lcd_writezahl (int32_t zahl, uint8_t pos, uint8_t spacer) { int32_t output; char sign = '0'; pos--; // Korrektur des Parameters für Benutzerfreundlichkeit if (spacer) sign=' '; // negatives Vorzeichen oder Leerzeichen if (zahl < 0) { lcd_writechar ('-'); zahl *= -1; // positive Zahl } output = zahl; // Hunderttausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender Nullen) if (zahl >= 100000) lcd_writechar (0x30 + output/100000); else if (pos >= 5) lcd_writechar (sign); output = output % 100000; // Zehntausender-Dezimalstelle oder Leerzeichen (Ausblenden fuehrender Nullen) if (zahl >= 10000) lcd_writechar (0x30 + output/10000); else if (pos >= 4) lcd_writechar (sign); output = output % 10000; // Tausender-Dezimalstelle oder Leerzeichen if (zahl >= 1000) lcd_writechar (0x30 + output/1000); else if (pos >= 3) lcd_writechar (sign); output = output % 1000; // Hunderter-Dezimalstelle oder Leerzeichen if (zahl >= 100) lcd_writechar (0x30 + output/100); else if (pos >= 2) lcd_writechar (sign); output = output % 100; // Zehner-Dezimalstelle oder Leerzeichen if (zahl >= 10) lcd_writechar (0x30 + output/10); else if (pos >= 1) lcd_writechar (sign); // einer Dezimalstelle oder Leerzeichen lcd_writechar (0x30 + output % 10); } // Zeilenwechsel void lcd_gotoline (uint8_t zeile) { if (zeile == 1) lcd_write(0x80,0); // B 1000 0000 => DD-RAM Adress Set 1. Zeile/1.Spalte if (zeile == 2) lcd_write(0xC0,0); // B 1100 0000 => DD-RAM Adress Set 2. Zeile/1.Spalte (B x100 0000 = H 40) } // Cursorpositionieren (Zeile, Spalte) void lcd_gotopos (uint8_t zeile, uint8_t spalte) { if (zeile == 1) lcd_write(0x80+spalte-1,0); // DD-RAM Adress 1. Zeile + Spalte if (zeile == 2) lcd_write(0xC0+spalte-1,0); // DD-RAM Adress 2. Zeile + Spalte } // Portrichtung einstellen void lcd_port_ini () { DDRC = 0x3F; // setze Portrichtung (1 = Ausgang): 0011 1111 } // Display initialisieren. Einmal als erstes aufrufen void lcd_ini () { lcd_port_ini(); PORTC=0x00; // alle Leitungen LOW delay(16000); // 10ms warten bis LCD wirklich bereit (max. Wert lt. Datenblatt) lcd_write_init(0x30); // init 1 delay(4100); lcd_write_init(0x30); // init 2 delay(100); lcd_write_init(0x30); // init 3 delay(100); lcd_write_init(0x20); // B 0000 0010 => mit 8-Bit-Command in 4-Bit-Modus umschalten delay(1000); // sicherheitshalber warten // ab jetzt 4-Bit-Modus lcd_write(0x28,0); // B 0010 1000 => Function Set: 4Bit (kein 8-Bit Bus), zweizeiliges Display, 5x7 Dots/Zeichen (kein 5x10) lcd_write(0x0C,0); // B 0000 1100 => Display On/Off: Display ein, Cursor aus, Blinken aus (0c0C) Cursor an: 0x0E lcd_write(0x06,0); // B 0000 0110 => Entry Mode Set: DD-RAM autom. inkr., Cursor bewegen lcd_cls(); // Display löschen }
Klaus Wachtler schrieb: > Vielleicht macht es auch Sinn, mit etwas zu starten, das besser > dokumentiert und wartbar ist. > Dafür ist dein lcd_tools.h vielleicht die falsche Wahl. Möchte gerne die Routine verwenden, da ich gerne auf der Basis von Blafusel meine ersten gehversuche mit OBD machen möchte.
Hier geht es um das IO-Board http://www.blafusel.de/misc/atmega8_io.html Dort steht in der Hardwareauflistung: Anschluß für ein LCD (beachte die Einführung zum C-Control LCD-Modul!) Wenn man da drauf klickt kommt man zu: http://www.blafusel.de/misc/ccontrol2.html#1 Und dort steht: Das LCD ist ein Standard Dot-Matrix LC-Display (und bitte nicht "LCD Display"!) mit HD44780/KS0070B/KS0076B kompatiblen Controller von Electronic Assembly mit 2x24 Zeichen in weißer Schrift bei blauer Hintergrundbeleuchtung (EA W242B-NLW). Prinzipiell sind auch andere LCDs möglich.
Die Frage ist jetzt: Hat's etwas gebracht? Oder wie verhält sich das Display jetzt? PS: Im Code steht: "R/W ist n.c." Ich hoffe doch, dass du das auf Ground gelegt hast?
> Die Frage ist jetzt: Hat's etwas gebracht? Oder wie verhält sich das > Display jetzt? Sorry hatte ganz vergessen dazu was zu schreiben :-D Nein hat leider garnix gebracht. Genau so wie vorher :-( > PS: Im Code steht: "R/W ist n.c." Ich hoffe doch, dass du das auf Ground > gelegt hast? Ja habe ich... R/W und D0 bis D3.
Dann fallen mir nur folgende Punkte ein: - Passt die F_CPU Einstellung zum tatsächlichen Takt? Daraus leiten sich ja die Delays ab. - Gibt es durch zu hohes F_CPU irgendwelche Überläufe innerhalb von _delay_loop_2 ? - Den "delay(64)" in "lcd_flash_e" löschen, der ist überflüssig. Wenn das nichts hilft, prüf nochmal die Schaltung nach. Insbesondere: Ist die Versorgungsspannung ausreichend (5V) und stabil? Denn wenn ich mir das Bild ansehe: Da sind etliche Buchstaben im einen Pixel zuweit nach rechts gerutscht. Das kann eigentlich nicht durch Software zustandekommen. Wenn das immer noch nichts bringt: Gehe zurück auf Start und mach das schon erwähnte Tutorial.
A.H. schrieb: > - Passt die F_CPU Einstellung zum tatsächlichen Takt? Daraus leiten > sich ja die Delays ab. Ja die passt. > - Gibt es durch zu hohes F_CPU irgendwelche Überläufe innerhalb von > _delay_loop_2 ? Nachdem ich die Fuses auf 1 mhz und im Makefile 1MHZ eingetragen habe geht es..... Ich brauche aber die 8MHZ für die OBD anwendung oder?
Nach Strom weg, Strom drauf ist wieder alles beim alten.... Nix geht mer -.- Ich verzweilfel langsam -.-
Beim googlen hab ich herausgefunden, das dort wahrscheinlich ein SPLC780D verbaut ist. In wie weit der sich vom Standard unterscheidet kann ich nicht sagen. Einfach mal schauen, wie man das Teil richtig initialisiert. Beitrag "Bibliothek fuer SPLC780D" http://www.oppod.com/pdf/TC1602A_Manual.pdf Gruß Skriptkiddy
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.