LCD HD44780 Atmega16 und PCF8574

Gast #4601600
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
}
Gast #4601629
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
Gast #4601631
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.
Gast #4601633
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.
#4601635
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();
#4601638
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.
#4601642
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?
Gast #4601651
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
(Firma: Vescomp) #4601664
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.
#4601680
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!
Angehängte Dateien:
(Firma: Vescomp) #4601701
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.
(Firma: Vescomp) #4601731
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.

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