Forum: Mikrocontroller und Digitale Elektronik hd44780 initialisierung


von logan (Gast)


Lesenswert?

Hallo,
ich versuche schon seit Stunden vergeblich etwas
auf einem LC-Display zu bewegen.
Das Display wird über den HD 44780 gesteuert und diesen möchte ich
wiederum über den Atmega168 steuern.
(interner Takt - default - 1MhZ)
Pin-Belegung und Anschluss wurde mehrfach getestet und stimmt.

Ich habe es mit folgendem Programm versucht:
http://www.mikrocontroller.net/articles/Erweiterte_LCD-Ansteuerung

Klappt natürlich nichts davon.
Nun wollte das Display wenigstens erstmal Initialisieren und dabei
den Cursor auf blinken stellen.
Um das ganze Schritt für Schritt zu verstehen habe ich alles
nacheinander geschrieben - ohne Funktionsaufruf etc.

Leider klappt immer noch nichts.
Ich möchte gern den Quelltext hier mal posten und hoffe das
mich jemand auf meine Fehler aufmerksam macht.

Bitte reißt mir nicht gleich den Kopf ab - ich bin Anfänger in C.
1
Header: main.h
2
3
#ifndef F_CPU
4
#define F_CPU 1000000
5
#endif
6
7
8
Header: lcd.h
9
10
#define LCD_PORT      PORTC
11
#define LCD_DDR       DDRC
12
#define LCD_DB        PC0
13
#define LCD_RS        PC4
14
#define LCD_EN        PC5
15
16
17
Source: main.c
18
19
#include <avr/io.h>
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include "main.h"
24
#include "lcd.h"
25
#include <util/delay.h>
26
27
 
28
int main (void) 
29
{
30
31
DDRD = (1 << PD0);    // PIN D0 Ausgang
32
PORTD = (0 << PD0);    // auf LOW da RW angeschlossen
33
34
uint8_t data;
35
uint8_t data2;
36
37
//*********** Initialisierung ******************************************
38
    _delay_ms (100);
39
40
  LCD_PORT = 0b00000011;        // muss 3 mal gesendet werden
41
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
42
       _delay_us( 2 );             // kurze Pause
43
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
44
  _delay_ms (20);
45
46
  LCD_PORT = 0b00000011;        // 2
47
    LCD_PORT |= (1<<LCD_EN);      // Enable auf 1 setzen
48
       _delay_us( 2);          // kurze Pause
49
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
50
  _delay_ms (10);
51
52
  LCD_PORT = 0b00000011;        // 3
53
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
54
       _delay_us( 2 );          // kurze Pause
55
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
56
  _delay_ms (10);
57
58
  LCD_PORT = 0b00000010;        // 4bit-Modus einstellen
59
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
60
       _delay_us( 2 );          // kurze Pause
61
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
62
63
  _delay_ms (10);            // 10ms warten
64
65
//********4bit / 2 Zeilen /5x8
66
      LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0 setzen
67
    data = 0b00101000;        // 4bit / 2 Zeilen /5x8
68
    data2= data;
69
   //obere 4 Bits senden   
70
    data &= 0xF0;                       // obere 4 Bit maskieren
71
        LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
72
      LCD_PORT |= (data>>(4-LCD_DB));     // obere Bits setzen
73
    
74
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
75
       _delay_us( 2 );          // kurze Pause
76
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
77
78
  //untere 4 Bits senden
79
    data2 = data2 << 4;
80
     data2 &= 0xF0;                      // untere 4 Bit maskieren
81
       LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
82
        LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
83
      
84
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
85
       _delay_us( 2 );          // kurze Pause
86
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
87
88
      _delay_us(100);
89
90
//******** Display Ein / Cursor Ein / blinken
91
    LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0 setzen
92
    data = 0b00001111;        // Display Ein / Cursor Ein / blinken
93
    data2= data;
94
95
   //obere 4 Bits senden  
96
    data &= 0xF0;                       // obere 4 Bit maskieren
97
        LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
98
      LCD_PORT |= (data>>(4-LCD_DB));     // obere Bits setzen
99
    
100
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
101
       _delay_us( 2 );          // kurze Pause
102
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
103
104
  //untere 4 Bits senden
105
    data2 = data2 << 4;
106
     data2 &= 0xF0;                      // untere 4 Bit maskieren
107
       LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
108
        LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
109
      
110
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
111
       _delay_us( 2 );          // kurze Pause
112
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
113
114
      _delay_us(100);
115
116
//******** Cursor ink / kein Scrollen
117
    LCD_PORT &= ~(1<<LCD_RS);      // RS auf 0 setzen
118
    data = 0b00000100;        // Cursor ink / kein Scrollen
119
    data2= data;
120
   //obere 4 Bits senden
121
    data &= 0xF0;                       // obere 4 Bit maskieren
122
        LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
123
      LCD_PORT |= (data>>(4-LCD_DB));     // obere Bits setzen
124
    
125
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
126
       _delay_us( 2 );          // kurze Pause
127
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
128
129
  //untere 4 Bits senden
130
    data2 = data2 << 4;
131
     data2 &= 0xF0;                      // untere 4 Bit maskieren
132
       LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
133
        LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
134
      
135
    LCD_PORT |= (1<<LCD_EN);       // Enable auf 1 setzen
136
       _delay_us( 2 );          // kurze Pause
137
       LCD_PORT &= ~(1<<LCD_EN);      // Enable auf 0 setzen
138
139
      _delay_us(100);
140
//*********** Initialisierung ENDEN *************************************
141
142
   while(1)   {    
143
   }                        
144
   return 0;
145
}

von holger (Gast)


Angehängte Dateien:

Lesenswert?

Hier eine HEX Datei für dich. Was siehst du da?

von holger (Gast)


Lesenswert?

Du setzt deine PORTC Pins für das LCD nicht auf Ausgang.

von logan (Gast)


Lesenswert?

holger schrieb:
> Du setzt deine PORTC Pins für das LCD nicht auf Ausgang.

Das stimmt natürlich.
Nachdem ich dies tat blinken sehr kurz alle Pixel auf beim flashen,
dann ist wieder ein Pixelloses Display zu sehen...

holger schrieb:
> Hier eine HEX Datei für dich. Was siehst du da?

Wie kann ich die .HEX mit meinem AVR Studio 4 verarbeiten und auf den µC 
flashen?

von Cyblord -. (cyblord)


Lesenswert?

Wie wärs mal mit Code in Funktionen kapseln? Siehst du nicht dass im 
Code immer dasselbe nur mit anderen Werten passiert? So ist das doch 
auch total unübersichtlich. Mach dir Funktionen. send_command(), 
send_data() usw.

von holger (Gast)


Lesenswert?

>Das stimmt natürlich.
>Nachdem ich dies tat blinken sehr kurz alle Pixel auf beim flashen,
>dann ist wieder ein Pixelloses Display zu sehen...

Was soll auch mehr passieren? Du schreibst ja nichts auf das Display.

>Wie kann ich die .HEX mit meinem AVR Studio 4 verarbeiten und auf den µC
>flashen?

Das musst du selber rausfinden. Ich benutze AVR Studio nicht.

von Ben _. (burning_silicon)


Lesenswert?

Du kannst die .hex-Datei einfach im Flash-Tool auswählen...

ATMega PortC? JTAG deaktiviert?

von holger (Gast)


Lesenswert?

>ATMega PortC? JTAG deaktiviert?

ATMega168 und JTAG?

von Ben _. (burning_silicon)


Lesenswert?

Hat der sowas nicht? Okay, ein Problem weniger...

von logan (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen!

holger schrieb:
> Was soll auch mehr passieren? Du schreibst ja nichts auf das Display.

Ich hab aber beim Initialisieren eingestellt das der Cursor blinken 
soll.

holger schrieb:
> Hier eine HEX Datei für dich. Was siehst du da?

Es hat funktioniert - das Display bleibt zu Beginn Pixellos.
Nach etwa 3sek leuchtet die erste Zeile mit weißen Pixeln, in der 
unteren sind wohl unbetätigte Pixel zu sehen. [vgl. Bild]
Was genau sollte denn passieren?

Ich betreibe das Display im 4bit-Modus.
Dazu habe ich die 4 unbenutzten Datenleitungen auf GND geklemmt.
RW ist an PD0 angeschlossen, welches ich auf LOW lege damit es 
funktioniert.

von Michael A. (Gast)


Lesenswert?

Mit welcher Frequenz arbeitet dein ATmega168? Sind die Fuses richtig 
gesetzt?

von logan (Gast)


Angehängte Dateien:

Lesenswert?

Michael A. schrieb:
> Mit welcher Frequenz arbeitet dein ATmega168? Sind die Fuses richtig
> gesetzt?

Die Fuses sind alle auf default.
Er sollte also mit 1 MHz arbeiten.
Ich habe über die delay Funktion mal einen Ausgang "blinken" lassen, die 
Frequenz hat gepasst.


Im Datenblatt des Moduls gibt es auch dieses Init.-Schema: [vgl. Bild]

Mir erschließen sich jeweils die zweiten Zeilen in welchen N, F, D, C 
usw. drin stehen nicht ganz.

von logan (Gast)


Lesenswert?

ist es denn ein Problem das ich das Display über etwa 20cm 
Flachbandkabel angeschlossen habe?

von holger (Gast)


Lesenswert?

>Ich betreibe das Display im 4bit-Modus.
>Dazu habe ich die 4 unbenutzten Datenleitungen auf GND geklemmt.
>RW ist an PD0 angeschlossen, welches ich auf LOW lege damit es
>funktioniert.

Lass die unbenutzten Leitungen offen.
RW beachtet mein Programm nicht. Schliess das mal fest an GND.
Und dreh dann mal am Kontrast.

von logan (Gast)


Lesenswert?

holger schrieb:
> Lass die unbenutzten Leitungen offen.

Dann weisen alle ein High auf.

> RW beachtet mein Programm nicht. Schliess das mal fest an GND.
> Und dreh dann mal am Kontrast.


Kontrast ist fest auf GND.

Dein Programm verwendet auch wirklich den Port C und hat genau die 
PIN-Belegung wie es bei mir der fall ist?

von Spess53 (Gast)


Lesenswert?

Hi

>> Lass die unbenutzten Leitungen offen.
>Dann weisen alle ein High auf.

Das ist auch richtig so. Der Displaycontroller hat interne 
Pull-Up-Widerstände.

>Kontrast ist fest auf GND.

Das passt bei den wenigsten Displays wirklich.

> in der unteren sind wohl unbetätigte Pixel zu sehen. [vgl. Bild]

Nein, das ist das Ergebnis einer falschen Kontrasteinstellung. Mach es 
wie alle anderen auch und benutze einen Einstellregler.

MfG Spess

von holger (Gast)


Lesenswert?

>> Lass die unbenutzten Leitungen offen.
>
>Dann weisen alle ein High auf.

Das macht nichts. Ich hab die unbenutzten Leitungen noch nie
angeschlossen und trotzdem geht es mit allen meinen Displays.

>Kontrast ist fest auf GND.

Das ist nicht gut. Da sollten so ca. 1V sein.

>Dein Programm verwendet auch wirklich den Port C und hat genau die
>PIN-Belegung wie es bei mir der fall ist?

Ja.

von logan (Gast)


Lesenswert?

Ich habe grad über ein Spannungsteiler 1V eingestellt.
Keine Veränderung.

Leider habe ich bemerkt das mein Wannenstecker wohl einen kleinen 
Wackelkontakt hat.
Wenn ich an ihm wackle, dann verschindet manchmal der untere Balken...

Nach welchem Kontakt der 12 benötigten riecht das?

von logan (Gast)


Lesenswert?

Wackler ist behoben... war wohl nicht die Ursache...

von holger (Gast)


Lesenswert?

>Ich habe grad über ein Spannungsteiler 1V eingestellt.
>Keine Veränderung.

Dann musst du die Spannung so lange größer machen bis sich was ändert.
Am besten du baust einen Trimmer oder ein Poti ein.
Bei meinem blau weissen Display war der Bereich für den
besten Kontrast ziemlich eng.

von beginner (Gast)


Lesenswert?

Also meint ihr das der Kontrast auf max steht und ich deshalb
nichts auf dem Display erkennen kann?
Ich werde es mal probieren...

aber nochmal generell zu meinem Quellcode oben:

Eigentlich sollte nach der Initialisierung nichts außer ein blinkender 
Cursor zu sehen sein, oder?

Hat jemand das o.g. Bild aus dem Datenblatt, welches den Ablauf der 
Initialisierung darstellt, verstanden?
Sieht irgendwie etwas anders aus als der gewöhnliche Ablauf...

von beginner (Gast)


Lesenswert?

gut - ich hab ein Poti gefunden und mal angeklemmt:

0,0 V - beiden Zeilen komplett da (jedes Pixel weiß)
0,5 V - untere Zeile beginnt zu verschwinden
1,0 V - obere Zeile beginnt zu verschwinden, untere Zeile weg
2,0 V - beide Zeilen komplett weg (Display nur noch blau)

Nun frag ich mich - welche Einstellung/Spannung ist denn richtig?

holger schrieb:
> Hier eine HEX Datei für dich. Was siehst du da?

Das war drauf. Gesehen hab ich nichts.

Es kann doch nicht so schwer sein - ich sitz nun schon fast 2 Tage dran 
und nichts ändert sich... die Pausen Zeiten in meinem Programm sind 
teilweise deutlich höher als gefordert, aber das ist ja nicht schlimm, 
oder?
In der .HEX von Holger scheinen diese ja richtig zu sein - trotzdem 
passiert nichs...

von Spess53 (Gast)


Lesenswert?

Hi

>Nun frag ich mich - welche Einstellung/Spannung ist denn richtig?

Wenn die untere Zeile verschwunden ist.

Wenn in der ersten Zeile die Dots komplett eingeschaltet sind, bedeutet 
das, das das Display nicht initialisiert wird. Mich wundert alllerdings, 
das deine Anzeige erst nach 3 Sekunden erscheint. Normaler weise 
passiert das sofort nach dem Einschalten.

MfG Spess

von beginner (Gast)


Lesenswert?

ok - also benötigt das Display etwa 1V. Wie holger auch bereits schrieb.

Ich weiß nun das die Taktrate stimmt und alles Richtig angeschlossen 
ist.

Nun kann es ja nur noch am Code liegen.
Und dieser kann ja nicht schritt für schritt getestet werden, sondern 
muss als ganzes funktionieren, sodass das Display initialisiert wird.

Ich muss nun zum dritten mal fragen:

Versteht jemand den Init-PAP aus dem Datenblatt den ich als Bild 
hochgeladen hab?

von holger (Gast)


Lesenswert?

>Nun kann es ja nur noch am Code liegen.

Es könnte auch an einem defekten Display liegen.
Hast du das Teil mal verpolt?

von beginner (Gast)


Lesenswert?

Es läuft! :-)
Vielen Dank an alle die mich unterstützt haben.

Nachdem ich den Kontrast richtig eingestellt habe (1,6 V)
habe ich ja nun noch mehrfach versucht zu flashen - erfolglos.

Nun habe ich gemerkt das ich die .HEX die ich ständig flashe sich seit 
stunden nicht geändert hat (Datum der Änderung), obwohl ich genau dieses 
Projekt geöffnet hatte.
Ich bin dann statt wie üblich auf "Bild Active Conf" (F7)auf Build and 
Run gegangen (Strg + F7).
Und siehe da - die .HEX hat sich geändert und es lief...

Es lag anfangs also am Kontrast und nun zum Schluss an dieser 
Dummheit...

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.