Hallo allerseits, ich bin seit einigen Tagen wieder an einem älteren Projekt. Es soll eine universelle Steuerungsplatine mit Funkmodul, Relais, Zeitschaltuhr usw. werden (bzw. ist es bereits). Nun, das Problem ist, dass gerade für Zeiteinstellungen ein Display unerlässlich ist. Verbaut ist ein LCD, welches über I2C angesteuert wird. Nach unzähligen fehlgeschlagenen Versuchen habe ich dieses erstmal "ignoriert" und ein paralleles LCD angeschlossen. Es handelt sich dabei um das Modell "DMC16202 NYU-LY" (2x16) mit einem HD44780-Controller. Ich möchte es gerne im 4-Bit-Modus betreiben und habe es gemäss den unzähligen Anleitungen im Internet angeschlossen (DB4-DB7 als Datenleitungen, RW/EN&RS als Steuerleitungen). Nun bin ich seit einigen Tagen am testen, doch leider funktioniert immer noch nichts. Die Initialisierung klappt nicht. Ich weiss, dass es schon zu viele Threads über dieses Thema gibt, aber ich habe das Gefühl, dass ich jeden einzelnen durchgekämmt habe. Ist ja im Prinzip auch nicht schwierig, deshalb verstehe ich ja auch nicht, warum es bei mir nicht funktionieren will. Das Display zeigt nach der Initialisierung einen blinkenden Cursor an zufälliger Position auf der 1. Zeile an. Der Kontrast ist über ein Poti eingestellt (1. Zeile noch leichte schwarze Flächen, 2. Zeile nichts, obwohl in Initialisierung auf 2-zeilig eingestellt wird). Die Initialisierungs-Routine habe ich aus dem Datenblatt übernommen (http://www.kyocera-display.com/pdf/Dmcman_full.pdf) Es wäre wirklich nett, wenn sich jemand den Code anschauen könnte. Die Funktionen habe ich aus Projekten aus der Schule adaptiert. Die main.c habe ich nicht angehängt, mache noch nichts anderes als die Initialisierung. Vielen Dank schonmal! Herr Vorragend
Max Vorragend schrieb: > Kann mir niemand helfen?
1 | > default: lcd_send_data(get_spec_char(ch)); //Zeichen an LCD senden |
Und wo ist lcd_send_data und lcd_send_command ?
:
Bearbeitet durch User
Vielen Dank für deine Antwort! lcd_send_data und lcd_send_command sind beide in display_44780.h als Makros festgelegt. Sie greifen beide auf die lcd_send Funktion zu. Sollte doch funktionieren so oder nicht? mfg Herr Vorragend
Oder liegt ein Missverständnis vor? Deine Frage war schon, wo die Funktionen definiert sind? mfg Herr Vorragend
Möglicherweise ein Timingproblem. LCD_EN = _OFF;//0; //Oberes Nibble senden LCD_EN = _ON;//1; ist vielleicht ein bisschen schnell. Warum nicht: RS, RW, Dx setzen t_as abwarten E high setzen PW_EH warten E low setze t_Cycle erfüllen.
Also, nun sieht es folgendermassen aus: -50ms abwarten -RW, RS & EN auf 0, Datenpins gemäss Initialisierung HD44780 -25ms abwarten -EN auf 1 (pos. Flanke) -25ms abwarten -EN auf 0 (oberes Nibble senden) -50ms abwarten -gleicher Ablauf mit unterem Nibble Ergebnis: Immer noch genau gleich, Cursor blinkt (an ca. 4. Stelle) auf 1. Zeile, zweite Zeile funktioniert nicht. Der Cursor kann auch nicht verschoben werden, also muss das Problem ja immer noch in der Initialisierung liegen... Noch irgendwelche Ratschläge oder Tipps?
#define lcd_send_command(command) lcd_send(command) Also ist das ein und das selbe (wozu soll das gut sein???) Mit dieser Routine sendest du immer oberes UND unteres Nibble eines Byte. Nur werden die ersten 4 Initialisierungsschritte im 8-Bit-Mode durchgeführt bei dem nur die Bits <D7:D4> übertragen werden - das untere Nibble <D3:D0> nicht. Siehe in deinem DB Seite 33 !!!
vielen Dank Chris für die Antwort, ich habe nun neue Routinen geschrieben, bzw. die Vorlage vom Tutorial zur LCD-Ansteuerung angepasst. Da ich die Pins des Displays nicht alle auf dem selben Port habe, musste ich vorallem die "lcd_out"-Routine anpassen. Leider funktioniert die Initialisierung immer noch nicht. Funktioniert die Routine so?
1 | static void tlcd_out(unsigned char data) //Sendet eine 4-bit Ausgabeoperation an das LCD |
2 | {
|
3 | LCD_D4 = checkbit(4,data); |
4 | LCD_D5 = checkbit(5,data); |
5 | LCD_D6 = checkbit(6,data); |
6 | LCD_D7 = checkbit(7,data); |
7 | |
8 | tlcd_enable(); |
9 | }
|
1 | unsigned char checkbit (unsigned char pos, unsigned char var) |
2 | {
|
3 | return ((1 << pos) & var); |
4 | }
|
Vielen Dank für die Hilfe!
Du brauchst doch nur von deiner ursprüngliche <lcd_send> eine 2. Version für den 8-Bit-Mode bei der Initialisation wo der Teil mit dem Lower Nibble wegfällt z.B: void lcd_send_m8 (unsigned char value){ LCD_EN = _ON;//1; //Pos. Flanke am Enable-Pin LCD_D7 = bit_test(value,7); //Oberes Daten-Nibble anlegen LCD_D6 = bit_test(value,6); // LCD_D5 = bit_test(value,5); // LCD_D4 = bit_test(value,4); // delay_ms(1); LCD_EN = _OFF;//0; //Oberes Nibble senden delay_us(30); //Maximaler Zeitbedarf einer Übertragung (blocking) } und die ersten 4 Initaliserungsschritte ersetzen durch lcd_send_m8(0b0011/**/0000); //Auf 8-Bit setzen #1 delay_ms(250); lcd_send_m8(0b0011/**/0000); // " #2 delay_ms(250); lcd_send_m8(0b0011/**/0000); // " #3 delay_ms(250); lcd_send_m8(0b0010/**/0000); //Auf 4-Bit setzen delay_ms(100);
>Funktioniert die Routine so? Ich würde sagen: Nein. checkbit() liefert dir kein Bit zurück sondern ein unsigned char. Einfach mal Beispiel rechnen: > LCD_D4 = checkbit(4,data); checkbit(4,data); liefert 0x00 oder 0x10 zurück. 0x10 passt nicht in ein Bit. In LCD_D4 wird nur das unterste Bit geschrieben, und das ist Null. Dito für die anderen Aufrufe. Besser wäre wohl:
1 | unsigned char checkbit (unsigned char pos, unsigned char var) |
2 | {
|
3 | if((1 << pos) & var) return 1; |
4 | return 0; |
5 | }
|
Wobei variables schieben fast immer teuer ist. Einfach nur: if(data & (1<<4)) LCD_D4 = 1; else LCD_D4 = 0; würde es schneller tun.
Vielen Dank Chris & Holger, Mit der Vorlage aus dem Tutorial und Holgers Korrektur meiner Checkbit-Funktion läuft das Display nun endlich!
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.