LCD "PWB16202" an PIC18F65J50

#3791120
Lesenswert?

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
Angehängte Dateien:
Gast #3829866
Lesenswert?

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.
#3829948
Lesenswert?

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?
#3829976
Lesenswert?

#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 !!!
#3831766
Lesenswert?

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!
#3831939
Lesenswert?

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);
Gast #3831946
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren