Forum: Mikrocontroller und Digitale Elektronik LCD mit PCF8574 Frage


von Pete (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche, ein LCD (HD44780 komp.) mit einem PCF8574 zum Leben zu 
erwecken.

Irgendwie funktioniert aber die Initialisierung nicht. 
Kontasteinstellung ist wohl ok, ich sehe teilweise die Zeichenmatrix.

Den 8574 kann ich ansprechen, das ist soweit ok.
I2C Lib ist von Peter Fleury.
Anbindung wie bei ASURO (siehe Bild).

Sorry, dass der Code etwas lang geworden ist.

Hier der InitCode:
1
////// PCF8574 PINS
2
3
#define LD4  0  // Pin to Data Bus 4
4
#define LD5  1  // Pin to Data Bus 5
5
#define LD6  2  // Pin to Data Bus 6
6
#define LD7  3  // Pin to Data Bus 7
7
8
#define LRS  4  // Pin to RS Pin (Register Select)
9
#define LRW  5  // Pin to Read/Write Pin
10
#define LEN  7  // Pin to Enable Pin
11
#define LBL  6  // Backlight Pin, not used
12
13
#define LCD_INIT  {0b00000010,0b00001000, 0b00000000, 0b00001000, 0b00000000, 0b00000001, 0b00000000, 0b00000110, 0} // siehe Seite 18 Datenblatt
14
15
void InitLCD(void)
16
{
17
  unsigned char init[] = LCD_INIT;
18
  unsigned char i = 0;
19
20
  SetIOLCD(0, LCD_EN);              // Start LCD Control, EN=0
21
  _delay_ms(15);                    // Wait LCD Ready
22
23
  CommandLCD( LCD_8BIT | (LCD_8BIT >> 4) );
24
  _delay_ms(5);
25
  CommandLCD( LCD_8BIT | (LCD_8BIT >> 4) );
26
  _delay_ms(1);
27
  CommandLCD( LCD_8BIT | (LCD_8BIT >> 4) );
28
  _delay_ms(1);
29
  CommandLCD( LCD_8BIT | (LCD_4BIT >> 4) );
30
  _delay_ms(1);
31
32
  while (init[i] != 0x00)  // Hier sollten die 8 Kommandos geschickt werden
33
  {
34
    CommandLCD(init[i]); i++;
35
  }
36
  _delay_ms(1);
37
}
38
39
void CommandLCD(unsigned char command)
40
{
41
  if (command == LCD_HOME)  lineLCD = cursorLCD = 0x00;
42
  SetIOLCD(0, LCD_RS);
43
  SetDataLCD(command);
44
}
45
46
/* --------------
47
  LCD IO Ports schreiben
48
  \param  setCommand an - oder auschalten
49
  \param  bits  zu setzende bits
50
*/
51
void SetIOLCD(unsigned char setCommand, unsigned char bits)
52
{
53
  if (setCommand == 1)
54
    portLCD |= bits;
55
  else
56
    portLCD &= ~bits;
57
58
  i2c_start_wait(LCD_DEV+0);
59
  if (i2c_write(portLCD)) uart_puts("i2c Write failed.\n"); 
60
  i2c_stop();
61
}
62
/*------------
63
  LCD Daten schreiben
64
  \param  data auszugebende Date
65
*/
66
void SetDataLCD(unsigned char data)
67
{
68
  unsigned char dataPins;             // Pin Compatibility
69
70
  // Set First Nibble Data to DataPins on PCF8574
71
  dataPins &= 0x00;
72
  dataPins |= ((data & 0x80) >> 7) << LD7;
73
  dataPins |= ((data & 0x40) >> 6) << LD6;
74
  dataPins |= ((data & 0x20) >> 5) << LD5;
75
  dataPins |= ((data & 0x10) >> 4) << LD4;
76
77
  SetIOLCD(0, LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7); //Clear old Data Bit[7..4])
78
  SetIOLCD(1, dataPins);             // Strobe High Nibble Command
79
  SetIOLCD(1, LCD_EN);               // Enable ON
80
  _delay_ms(1);
81
  SetIOLCD(0, LCD_EN);              // Enable OFF
82
83
  // Set Second Nibble Data to DataPins on PCF8574
84
  dataPins &= 0x00;
85
  dataPins |= ((data & 0x08) >> 3) << LD7;
86
  dataPins |= ((data & 0x04) >> 2) << LD6;
87
  dataPins |= ((data & 0x02) >> 1) << LD5;
88
  dataPins |= ((data & 0x01) >> 0) << LD4;
89
90
  SetIOLCD(0, LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7);     // Clear old LCD Data (Bit[7..4])
91
  SetIOLCD(1, dataPins);            // Strobe Low Nibble Command
92
  SetIOLCD(1, LCD_EN);              // Enable ON
93
  _delay_ms(1);
94
  SetIOLCD(0, LCD_EN);              // Enable OFF
95
  _delay_ms(1);                     // Wait LCD Busy
96
}

von Pete (Gast)


Angehängte Dateien:

Lesenswert?

Und die Beschaltung gemäß Asuro als Anhang.

von Falk B. (falk)


Lesenswert?

@ Pete (Gast)

>ich versuche, ein LCD (HD44780 komp.) mit einem PCF8574 zum Leben zu
>erwecken.

[[Port-Expander PCF8574]]

>Irgendwie funktioniert aber die Initialisierung nicht.
>Kontasteinstellung ist wohl ok, ich sehe teilweise die Zeichenmatrix.

>Sorry, dass der Code etwas lang geworden ist.

Das gehört in den Anhang. Netiquette

Ich sehr erstmal keinen direkten Fehler.

MFG
Falk

von Gerhard. (Gast)


Lesenswert?

Hallo Pete,

uberpruefe ob das "E" Strobe signal tatsaechlich funktioniert. Mir kommt 
vor Du musst das E signal mit den Rest der Saten ORen. Das LCD nimmt nur 
dann die neuen Daten an, wenn die Daten auf dem Datenbus liege und 
danach das E Signal getatset wird.



----\_____________________________________  RS

(je nach CMD oder Daten Mode)

__ _______________________________ ______
__X_______________________________X______  Datenbus DB4-DB7
     (Gueltiges Neues Datenwort)      (Naechstes...)
                          __
_________________________/  \_____________  E Strobe
                            ^
                            |___ Daten werden erst hier vom HD44780
                                 angenommen (gespeichert)

So will das LCD die Ansteuerung sehen. Deshalb wirst Du die PCF8874 
Daten drei mal senden muessen:

1) Datenwort = ((DB4-7) | RS=X | E=0)
2) Datenwort = ((DB4-7) | RS=X | E=1)
3) Datenwort = ((DB4-7) | RS=X | E=0)

Versuche es mal auf diese Weise. Du koenntest uebrigens auch das E 
signal direkt von einem zusaetzlichen Pin Deines MCU ansteuern. Dann 
wuerde ein PCF8574 Wort genuegen.

Gerhard

von Gerhard. (Gast)


Lesenswert?

Kleine Berichtigung: Die Reihenfolge der PCF8674 ist bei meinem Beispiel 
nur wahlkuerlich angenommen. Musst Du entsprechend umanedern.

Gerhard

von Pete (Gast)


Lesenswert?

@Gerhard

Das mit dem Enable dachte ich wird in den letzten 4 Zeilen des 
geposteten Codes gemacht.
Daten Anlegen und dann Enable High und High->Low setzen. (Siehe 
SetDataLCD)

von Gerhard. (Gast)


Lesenswert?

Versuche es mal so:

void SetDataLCD(unsigned char data)
{
  unsigned char dataPins;             // Pin Compatibility

  dataPins = data >> 4; // Schiebe DB4-7 in P0-P3 Bitbereich
  SetIOLCD(1, dataPins & 0x0F ); // P5=0,P4=1,P7=0, Daten=P0-3
  SetIOLCD(1, dataPins | 0x80);  // Setze P7
  SetIOLCD(1, dataPins & 0x7F ); // Clear P7

  // Sende den zweiten Daten Nibble
  dataPins = data & 0x0F; // Nur DB0-3 werden gebraucht, P4-P7=0
  SetIOLCD(1, dataPins & 0x0F ); // P5=0,P4=1,P7=0, Daten=P0-3
  SetIOLCD(1, dataPins | 0x80 ); // Setze P7
  SetIOLCD(1, dataPins & 0x7F ); // Clear P7

}

Ich wuerde SetIOLCD umaendern, so dass es nur ein 8-bit Datenwort 
aussendet und die Manipulierung der Busbits in der Anwender Routine 
vorgenommen wird.

Der Wert von P4 muss je nach DATEN Mode oder Command Mode eingestellt 
werden. P5 kann immer auf Null liegen solange BUSY nicht gelesen wird.

Jetzt sieht der HD44780 die Daten waehrend des Strobing des E Signals 
weil sich ja nur der Inhalt des P7 bits (E) aendert und alle anderen 
Daten anliegen.

Man koennte spaeter einen One-Shot an P7 anhaengen, welcher den E Pulse 
erzeugt und erspart sich die drei PCF8574 Sendungen bis auf eine.

Gerhard

von Gerhard. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Pete,

habe es mir nicht nehmen lassen, das mal selber aufzubauen und hat bei 
mir mit einem PIC18F8722, PCF8574A und einem zweizeiligen LCD auf Anhieb 
funktioniert. Werde spaeter mein Test Program hier im Anhang beilegen.

Gruss,
Gerhard

von Gerhard. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Pete,

im Anhang das versprochene Demo Programm. Also nicht aufgeben;-).

Es geht auf alle Faelle mit dem PCF8574A als LCD Bus Treiber. Die 
Zugriffsgeschwindigkeit ist sehr gut.

Wenn man eine kleine Zusatzschaltung verwendet liesse sich pro PCF8574 
dann ein Nibble uebertragen.

Werde mir warscheinlich selber eine kleine LCD Huckepack-platine 
erstellen. Ist auf jeden Fall sehr bequem ein LCD ueber I2C anzusteuern. 
Man kann dann die unbenutzten Bits fuer die LED Einschaltung verwenden. 
Mit einen billigen 8-bit I2C DAC koennte man auch noch den Kontrast 
einstellen. Vielen Dank mich auf diesen Weg hinzuleiten.

Gruss,
Gerhard

von Pete (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Gerhard,

danke für die bildlichen LCD Grüße :-)

Jetzt funktioniert es auch bei mir. Das mit dem Enable hat wohl nicht 
geklappt.

Auf jeden Fall eine super Sache so ein LCD über I2C :-)

Viele Grüße,
Pete

von Gerhard. (Gast)


Lesenswert?

Hallo Pete!

danke fuer die Erfolgsmeldung. Freut mich sehr;-). Dein Problem hat mir 
auch geholfen, da ich jetzt selber einen Treiber dafuer habe. Fuer mich 
war das auch das erste Mal einen PCF8574 anzusteuern.

Das tolle mit dem I2C LCD Interface ist jetzt, dass man nun bequem mehr 
als ein LCD ansteuern kann.

Ich habe vor eine kleine Platine oder einen Lochrasteraufbau zu 
verwirklichen der Huckepack hinter dem LCD sitzt. Mit den zwei 
unbenutzten PCF8574 Ausgaengen koennte man dann noch schon die B.L. LEDs 
schalten (3 Helligkeitsstufen).

Gruss,
Gerhard

von Sebastian (Gast)


Lesenswert?

Nur ein Tip nebenbei: Ein LCD mit eingebautem PCF8574 kann man bei 
Oppermann fertig kaufen: 
http://www.oppermann-electronic.de/html/januar_2008.html (Das "LCM 
015"). Wie das aussieht, sieht man hier: 
http://forum.lcdinfo.com/viewtopic.php?p=6887&sid=eb49d69ff690db3e36d06711c7cbaf74

...und die Anschlußbelegung wird hier verraten (auf polnisch, 2. Beitrag 
von oben): 
http://www.elektroda.net/uzytkowa/plmiscelektr/12_99_1/12_99_1297.htm

Netterweise ist auch gleich die Portzuordnung angegeben. Wie man in 
einem anderen Forum liest, bedeutet "Podœwietlenie" 
Hintergrundbeleuchtung.
Das Teil ist also ein industriestandard-kompatibles LCD mit eingebautem 
I2C-Portbaustein, fast genauso wie die in diesem Thread beschriebene 
Selbstbaulösung. Nur ao als kleiner Hinweis, nicht als Werbung 
mißzuverstehen - Ich bekomme keinerlei Provision.

von Gerhard. (Gast)


Lesenswert?

Hallo Sebastian,

vielen Dank fuer die Hinweise und Links. Immer gut zu wissen.

Gruss,
Gerhard

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.