Forum: Mikrocontroller und Digitale Elektronik LCD HD44780 Atmega16 und PCF8574


von Daniel (Gast)


Lesenswert?

Hallo ich versuche schon seit mehreren Tagen das LCD Display zum Laufen 
zu bringen. Ich weiß einfach nicht woran es liegt das ich kein Zeichen 
auf dem Display anzeigen lassen kann. Ich denke das es richtig 
initialisiert wird.
DIe Kommunkation zwischen dem Atmega16 und dem PCF8574 funktioniert. Hab 
statt dem Display LED angehängt. Ich nutze den voreingestellten Takt des 
Atmega16

Wo liegt der Fehler im Quellcode..?
1
/*
2
 * GccApplication1.c
3
 *
4
 * Created: 26.05.2016 20:58:27
5
 * Author : creme
6
 * LCD Pin Description
7
 * 1 - Vss (GND)
8
 * 2 - Vcc (+5V)
9
 * 3 - Vee (poti Kontrasteinstellung)
10
 * 4 - RS
11
 * 5 - R/W
12
 * 6 - E
13
 * 7 - DB0
14
 * 8 - DB1
15
 * 9 - DB2
16
 * 10 - DB3
17
 * 11 - DB4
18
 * 12 - DB5
19
 * 13 - DB6
20
 * 14 - DB7
21
 * PCF8574 Pin Description
22
 * P0 - DB4
23
 * P1 - DB5
24
 * P2 - DB6
25
 * P3 - DB7
26
 * P4 - RS
27
 * P5 - E
28
 * R/W - GND
29
 */ 
30
31
#include <avr/io.h>
32
#include <avr/interrupt.h>
33
//#include <avr/iom16.h> //ISR Vektoradresse mit Variablenbezeichnung
34
//#include "lcd-routines.h"
35
36
#include "i2clcd.h"
37
#include "i2cmaster.h"
38
39
//#define F_CPU 1000000UL
40
41
//#include "lcd.h"
42
//#include <avr/i2c>
43
#define DevPCF8457 0x40
44
uint8_t PCFPort = 0x00;
45
46
#define PC0 0
47
#define PC1 1
48
#define PC2 2
49
#define PC3 3
50
#define PC4 4
51
#define PC5 5
52
#define PC6 6
53
#define PC7 7
54
55
#define RS (1<<PC0)
56
#define RW (1<<PC1)
57
#define E (1<<PC2)
58
//#define PC3 (1<<3)
59
#define D4 (1<<PC4)
60
#define D5 (1<<PC5)
61
#define D6 (1<<PC6)
62
#define D7 (1<<PC7)
63
#define PX (1<<0)
64
65
66
#define SetDisplay 0x08
67
#define DisplayOn 0x04
68
#define CursorOn 0x02
69
#define CursorOff 0x00
70
#define CursorBlinkOn 0x01
71
#define CursorBlinkOff 0x00
72
73
#define LCDSetEntry 0x10
74
#define LCDEntryIncrease 0x04
75
#define LCDEntryDecrease 0x00
76
#define LCDShift 0x01
77
#define LCDNoShift 0x00
78
#define DisplayCursorShift 0x10
79
80
#define ClearDisp 0x01
81
82
#define FuncionSet 0x20
83
#define LCD4Bit 0x00
84
#define LCD2Lines 0x08
85
#define LCD5x7 0x00
86
87
88
uint16_t cnt=0;
89
uint8_t fin=0;
90
91
ISR(TIMER0_COMP_vect)
92
//Aufruf alle 2,04ms
93
{
94
  cnt++;
95
  if(cnt<=2451) //~5sec
96
  {  
97
    fin=1;
98
    cnt=0;
99
  }
100
  TCNT0 = 0;
101
}
102
103
void lcd_init_pcf(void)
104
{
105
  _delay_ms(16);
106
  
107
}
108
109
void LCD_Command_PCF(uint8_t data)
110
{
111
  //RS auf 0 setzen
112
  //i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
113
  //i2c_write((!RS));
114
  //i2c_stop();
115
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
116
  
117
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
118
  //i2c_write((!RS) | (data&0xF0)); //first high byte
119
  i2c_write((data&0xF0)); //first high byte
120
  i2c_stop();
121
  
122
  _delay_us(20);for(uint8_t i=0; i<=12;i++)_delay_ms(500); 
123
  
124
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
125
  //i2c_write((!RS) | (data<<4) ); //low byte
126
  i2c_write((data<<4) ); //low byte
127
  i2c_stop();
128
  _delay_us(84); //42
129
  
130
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
131
  
132
}
133
134
void LCD_Data_PCF(uint8_t data)
135
{
136
    //RS auf 1 setzen
137
    i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
138
    i2c_write(RS);
139
    i2c_stop();
140
    //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
141
    
142
    i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
143
    i2c_write(RS | (data&0xF0)); //first high bytes
144
    i2c_stop();
145
    
146
    //20 //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
147
    
148
    i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
149
    i2c_write(RS | (data<<4) ); //low bytes
150
    i2c_stop();
151
    
152
    _delay_us(92); //46
153
}
154
155
void LCD_Clear_PCF(void)
156
{
157
  LCD_Command_PCF(0x01);
158
  _delay_ms(6); //3
159
}
160
161
void pause(void)
162
{
163
}
164
165
int main(void)
166
{
167
  //Test
168
  DDRD |= (1<<PD6);
169
  PORTD &= ~(1<<PD6);
170
  //
171
  DDRC |= (1<<PC0) | (1<<PC1);
172
  i2c_init();
173
  
174
  _delay_ms(100); //16
175
  
176
    i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
177
    i2c_write(0x00);
178
    i2c_stop();
179
  
180
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
181
  _delay_us(20);
182
  
183
  //LCD Software Reset
184
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
185
  i2c_write(FuncionSet | D4); //1
186
  i2c_stop();  
187
  _delay_ms(10);//5 for(uint8_t i=0; i<=12;i++)_delay_ms(500);
188
  
189
  //Enable Pulse Signal
190
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
191
  i2c_write(FuncionSet | D4 | E); //2
192
  i2c_stop();
193
  _delay_us(40);// 20 for(uint8_t i=0; i<=12;i++) _delay_ms(500);
194
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
195
  i2c_write(FuncionSet | D4); //3
196
  i2c_stop();
197
  _delay_ms(2);//1for(uint8_t i=0; i<=12;i++)_delay_ms(500); 
198
  
199
  //Enable Pulse Signal
200
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
201
  i2c_write(FuncionSet | D4 | E); //4
202
  i2c_stop();  
203
  _delay_us(40);//20for(uint8_t i=0; i<=12;i++)_delay_ms(500); 
204
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
205
  i2c_write(FuncionSet | D4); //5
206
  i2c_stop();
207
  _delay_ms(2);//1 for(uint8_t i=0; i<=12;i++)_delay_ms(500); 
208
  
209
  //4-Bit Modus aktivieren
210
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
211
  i2c_write(FuncionSet | LCD4Bit); //6
212
  i2c_stop();
213
  
214
  _delay_ms(20);//5//for(uint8_t i=0; i<=12;i++)_delay_ms(500);  
215
  
216
  
217
  LCD_Command_PCF(FuncionSet | LCD4Bit | LCD2Lines | LCD5x7); //7, 8
218
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
219
  LCD_Command_PCF(SetDisplay | DisplayOn | CursorOff | CursorBlinkOff); //9,10
220
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
221
  LCD_Command_PCF(LCDSetEntry | LCDEntryIncrease | LCDNoShift);
222
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
223
  LCD_Clear_PCF();
224
  //for(uint8_t i=0; i<=12;i++)_delay_ms(500);
225
  LCD_Data_PCF('T');
226
  
227
  //PORTD &= ~(1<<PD6);
228
  
229
    while (1) 
230
    {
231
    
232
    }
233
}

von Frickelfritze (Gast)


Lesenswert?

Daniel schrieb:
> Wo liegt der Fehler im Quellcode..?

Das können wir nicht wissen solange wir keinen dazugehörigen
Schaltplan kennen. Und wenn gar nichts mehr hilft brauchen
wir auch noch ein Bild deines Aufbaus.

von Falk B. (falk)


Lesenswert?


von Georg G. (df2au)


Lesenswert?

Wo wird beim Schreiben eines Datenbytes das E Signal getoggled? Ich sehe 
nur, dass du per i2c_write die Nibbles ausgibst.

von Frickelfritze (Gast)


Lesenswert?

Daniel schrieb:
> #include "i2clcd.h"
> #include "i2cmaster.h"

Für die genaue Prüfung fehlen diese Dateien ....

von aSma>> (Gast)


Lesenswert?

Servus,
ich habe mal kurz das hier angeguckt: Ein redundanter, schlecht 
dokumentierter, die Hälfte ist auskommentiert, schlecht durchdacht und 
konzepierter Kod.

Um die ganzen Fehler zu zeigen, da nehmst du lieber gleich ne andere 
lib.

mfg

von Daniel (Gast)


Lesenswert?

i2clcd.h wird nicht verwendet, hatte es vergessen auszukommentieren.
i2cmaster.h das ist die Header Datei von Peter Fleury. Die I2C 
Kommunikation funktioniert...da braucht nichts überprüft werden.

Die Beschaltung ist folgende:

RS - P0
R/W - GND
E - P2
DB0-DB3 Pins offen
DB4 - P4
DB5 - P5
DB6 - P6
DB7 - P7

LCD ist heile, habs mit der normalen 4-Bit Ansteuerung bereits zum 
Laufen gebracht.

von Daniel (Gast)


Lesenswert?

//Enable Pulse Signal
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
  i2c_write(FuncionSet | D4 | E); //4
  i2c_stop();
  _delay_us(40);//20for(uint8_t i=0; i<=12;i++)_delay_ms(500);
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
  i2c_write(FuncionSet | D4); //5
  i2c_stop();
  _delay_ms(2);//1 for(uint8_t i=0; i<=12;i++)_delay_ms(500);

Ich setze ein Byte zeitgleich mit dem Enable Signal (High), anschließend 
wieder das gleiche Byte wobei das Enable Signal low ist.

von Falk B. (falk)


Lesenswert?

@ Daniel (Gast)

>Die Beschaltung ist folgende:

OK.

>LCD ist heile, habs mit der normalen 4-Bit Ansteuerung bereits zum
>Laufen gebracht.

Dann tu dir und auch uns einen Gefallen und bring einen HAUCH von 
Struktur in deinen Quelltext! Das Minimum isr die Verwendung einer 
Funktion, welche ein Nibble an das LCD schreibt. Dort gehört dann auch 
die Ansteuerung von E mit rein. Sonst wird das hier alles nur Chaos!!! 
Man braucht 3 Schreibzugriffe auf den I2C, Daten schreiben, E setzen, E 
löschen, wobei die Daten erhalten beleiben.

Etwa so
1
    // direct I2C access, write all three bytes in one cycle for faster operation
2
  i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
3
        i2c_write(data_out);                // setup data BEFORE E!   
4
  i2c_write(data_out | LCD_E);    // set E to high
5
  i2c_write(data_out);              // set E to low
6
  i2c_stop();

von Falk B. (falk)


Lesenswert?

@Daniel (Gast)

>Ich setze ein Byte zeitgleich mit dem Enable Signal (High), anschließend
>wieder das gleiche Byte wobei das Enable Signal low ist.

Das ist falsch! Die Daten müssen VOR der steigenden Flanke von E 
anliegen, sonst reagieren einige LCDs komisch.

von Daniel (Gast)


Lesenswert?

@Falk Bruner

den Quellcode von den Eichelmanns hatte ich anfangs auch ausprobiert... 
damit läuft es auch nicht... Was hast du geändert damit es ging?

von Daniel (Gast)


Lesenswert?

Ok, das könnte es sein, also vorher das Byte anlegen..teste ich mal

von Georg G. (df2au)


Lesenswert?

Daniel schrieb:
> void LCD_Data_PCF(uint8_t data)
> {
>     //RS auf 1 setzen
>     i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
>     i2c_write(RS);
>     i2c_stop();
>
>     i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
>     i2c_write(RS | (data&0xF0)); //first high bytes
>     i2c_stop();
>
>     i2c_start_wait(LCD_I2C_DEVICE+I2C_WRITE);
>     i2c_write(RS | (data<<4) ); //low bytes
>     i2c_stop();
>
>     _delay_us(92); //46
> }

Ich bin vermutllich blind... wo wird hier E bedient?

Wieso kann man das so nicht posten?
Muss ich noch Fülltext schreiben?

von Frickelfritze (Gast)


Lesenswert?

Eine passende Include Datei wäre nicht schlecht ....

../LCD_I2C_Test.c: In function 'LCD_Command_PCF':
../LCD_I2C_Test.c:118: error: 'LCD_I2C_DEVICE' undeclared (first use in 
this function)


Hier herrscht auch noch etwas Verwirrung:

Daniel schrieb:
> * PCF8574 Pin Description
>  * P0 - DB4
>  * P1 - DB5
>  * P2 - DB6
>  * P3 - DB7
>  * P4 - RS
>  * P5 - E
>  * R/W - GND

Daniel schrieb:
> Die Beschaltung ist folgende:
>
> RS - P0
> R/W - GND
> E - P2
> DB0-DB3 Pins offen
> DB4 - P4
> DB5 - P5
> DB6 - P6
> DB7 - P7

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
> Das ist falsch! Die Daten müssen VOR der steigenden Flanke von E
> anliegen, sonst reagieren einige LCDs komisch.

Daniel schrieb:
> Ok, das könnte es sein, also vorher das Byte anlegen..teste ich mal

 Wird kaum helfen.
 Es ist nur eine Mindesthaltezeit bis zur fallenden Flanke von Enable
 vorgeschrieben (min. 40-50ns).

 Obwohl es im Prinzip schon richtig ist - zuerst Daten anlegen, danach
 mit Steuersignalen rumspielen - Enable als letztes.

: Bearbeitet durch User
von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

@ Marc Vesely (Firma: Vescomp) (logarithmus)

>> Das ist falsch! Die Daten müssen VOR der steigenden Flanke von E
>> anliegen, sonst reagieren einige LCDs komisch.

> Wird kaum helfen.
> Es ist nur eine Mindesthaltezeit bis zur fallenden Flanke von Enable
> vorgeschrieben (min. 40-50ns).

FALSCH! Für RS und RW gilt eine SETUP-Zeit!!! Siehe Anhang!

> Obwohl es im Prinzip schon richtig ist - zuerst Daten anlegen, danach
> mit Steuersignalen rumspielen - Enable als letztes.

EBEN!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Daniel schrieb:
> Ich setze ein Byte zeitgleich mit dem Enable Signal (High), anschließend
> wieder das gleiche Byte wobei das Enable Signal low ist.

 Bei der Initsequenz (welche nicht richtig ist) schon, aber nicht beim
 LCD_Command_PCF(data) und LCD_Data_PCF(data).

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
>> Wird kaum helfen.
>> Es ist nur eine Mindesthaltezeit bis zur fallenden Flanke von Enable
>> vorgeschrieben (min. 40-50ns).
>
> FALSCH! Für RS und RW gilt eine SETUP-Zeit!!! Siehe Anhang!

 Aber nicht für E.
 Aber ich bin der selben Meinung wie du.
 Aber ich will nicht mit dir streiten.

 Aber im ernst:
 Fast jeder Steuersignal erwartet stabile Daten - ob das jetzt die
 steigende oder fallende Flanke ist - unwichtig.
 Deswegen sollte man sich angewöhnen, zuerst die Daten stabil anzulegen
 und die Zeit bis zum Befehl mit Steuersignal reicht dann schon.

 Aber mit RS und R/W hast du natürlich Recht.
 Setzen von RS oder R/W gleichzeitig mit Daten funktioniert nie und
 nimmer.

von Falk B. (falk)


Lesenswert?

@Marc Vesely (Firma: Vescomp) (logarithmus)

>> FALSCH! Für RS und RW gilt eine SETUP-Zeit!!! Siehe Anhang!

> Aber nicht für E.

Brille? Fielmann?

Schau dir mal tAS an, Setup von RS und R/W gegenüber der steigenden 
Flanke von E.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Falk B. schrieb:
> Brille? Fielmann?

 Mannomann.
 Okay, wenn du es so haben willst...

 Deine Ausage:
Falk B. schrieb:
> Das ist falsch! Die Daten müssen VOR der steigenden Flanke von E
> anliegen, sonst reagieren einige LCDs komisch.

 Und das ist falsch - Daten müssen nicht VOR der steigenden Flanke
 von E anliegen.


> Schau dir mal tAS an, Setup von RS und R/W gegenüber der steigenden
> Flanke von E.

 Das besagt doch nur, dass RS und/oder R/W  mindestens 30ns vor der
 steigenden Flanke von E aktiviert sein müssen, schreibt also nur die
 Reihenfolge für Steuersignale vor.

 Hat aber mit Datenbus genau nichts zu tun - ich kann Daten vorher,
 nachher oder gleichzeitig mit diesen Signalen ändern.
 Und dann ist nur vorgeschrieben, dass Daten mindestens 40ns vor der
 fallenden Flanke von E stabil sein müssen.

 Ich kann also RS setzen, 40ns abwarten, E setzen, eine Woche abwarten,
 Daten schreiben, 40ns abwarten und E rücksetzen.
 Es wird funktionieren.

von Georg G. (df2au)


Lesenswert?

Wie lange wird es noch dauern, bis der TO liest, dass er das E Signal 
beim Schreiben der Daten vergessen hat? Dagegen sind die Timings 
Peanuts.

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.