Forum: Mikrocontroller und Digitale Elektronik LCD im 4-Bit Modus mit microchip 16F818 in C


von Masood M. (noob19)


Angehängte Dateien:

Lesenswert?

Hi @ all

Ich will mit einem Microchip 16F818 ein 16x2 LCd ansteuern.

Ich bin ein super Neuling im bereich C.
Habe einen passenden code gesucht, denn ich auch verstehe, aber leider 
nix passendes gefunden. Meine Variante ist ziemlich arm, aber bis jetzt 
verstehe ich was ich da mache.

LCD: 
http://www.reichelt.de/?ACTION=3;ARTICLE=31653;GROUPID=;SID=26UdltsKwQARoAAGBRH3M2ea74ad3aed975aa737531eaf9583acd

Wer viel Zeit hat kann mir ja gerne eine schönere Variante erklären. Wer 
weniger Zeit hat einfach nur mein programm korrigieren damit es läuft.

Wenn ich was angezeigt komme, sei es auch nur ein Buchstabe/Zeichen, 
dann wäre das erstmal ein großer erfolg.

Zur Zeit leuchtet nur die Zweite Zeile komplett auf.

Ich bedanke mich im vorraus für eure Antworten.

von Darkleon (Gast)


Lesenswert?

Hallo!

Was mir sofort bei deinem Code aufgefallen ist ist folgendes:
1
void main()
2
{
3
while (1)
4
{
5
   LCD_INIT();
6
   LCD_SCHREIBEN();
7
8
}
9
}
In deiner Endlosschleife wird das LCD dauern initialisiert und mit Daten 
gefüttert. Da das LCD ein sehr langsames Bauteil ist, wirst Du nie was 
sehen, da die Initialisation mit dem Befehl (display clear) die Zeilen 
immer wieder löscht. Das Display muss man ja nur einmal initialisieren.

Um zumindest zu sehen, ob das LCD mit deinem Code irgendwas ausgibt 
musst Du Deine Befehle aus der Endlosschleife nehmen. Denn das LCD zeigt 
ja solange das gleiche an, bis Du wieder was neues sendest.
Nimm also Deine Befehle aus der Schleife.
1
void main()
2
{
3
   LCD_INIT();
4
   LCD_SCHREIBEN();
5
while (1)
6
{
7
Nop();
8
}
9
}

Was ich noch auf die schnelle gesehen hab. Die LCD Leitungen definierst 
Du nirgends als Output, oder? Oder sind die bei einem Reset schon vom 
PIC so geschaltet?
Versuch das mal und berichte, was das LCD dann macht. Für das durchsehen 
der Initialisation hab ich momentan keine Zeit ;)

MfG Darkleon

von Masood M. (noob19)


Lesenswert?

hi,

erstmal Danke für die Antwort.

leider war das nicht das Problem.

Komischerweise wird die komplette 2. Zeile schwarz, aber mehr tut sich 
nicht.

von Darkleon (Gast)


Lesenswert?

Mit welchem takt läuft Dein PIC?
Wie hast Du den Pin am LCD für den Kontrast (glaub der heißt Vo) 
beschalten?

In Deiner Init hast Du irgendwie nie delays drinnen. Glaub mich zu 
erinnern, dass nach dem Function Set usw.. im Datenblatt jeweils eine 
Mindestwartezeit drinnsteht. Muss ich später mal nachschauen.

Wegen der genauen Init kann ich auch erst etwas später nachschauen, aber 
kontrollier mal das, dann hast diese Fehlerquellen auch ausgeschlossen 
;)

MfG Darkleon

von Masood M. (noob19)


Lesenswert?

Also der Pic läuft mit 8MHZ.
Kontrast ist über einen 10 K Poti an 5V.

Also da wo im Datenblatt wartezeiten sind müssten welche drin sein.

Ich werde nochmal nach allen Befehlen so 100µs wartezeit einbauen.
Mal gucken was sich dann ergibt.

Ich denke aber nicht, dass das der Fehler ist.
Melde mich gleich nochmal.

von MagIO (Gast)


Lesenswert?

Die eine "schwarze" Zeile, die andere leer kommt eigentlich dann, wenn 
nicht mal die Initialisierung klappt. Ist das Display auch richtig 
angeschlossen? Beim 4 Bit Interface werden D4-D7 verdrahtet, D0 - D3 
sollten ... hmmm .... ja was denn ... pull up oder down ... weiß ich im 
moment nicht auswendig.

von Masood M. (noob19)


Lesenswert?

Also an den Delays lag es nicht.

Als D4 bis D7 ist angeschlossen.
D0-D3 ist einfach frei. Oder sollte das lieber an GND, aber auch im 
Tutorial hier auf der Seite steht, dass die einfach nicht angeschlossen 
werden sollen.

Daran sollte es nicht liegen.
Wenn dann wohl eher an einem Fehler beim Initialisieren. Ich habe schon 
mehr mals drüber geguckt, aber finde den Fehler leider nicht.

von MagIO (Gast)


Lesenswert?

Was ist mit dem R/W pin? Seh da keinen Code für.

von Masood M. (noob19)


Lesenswert?

Den R/W PIN habe ich auf GND gelötet.
Da ich nur schreibe und nicht lese brauche ich den nicht.

Ich habe mal meine Funktion "LCD_SCHREIBEN" auskommentiert und dann 
entshet keine "schwarze" zeile.

Jetzt ist die Frage ob der Fehler beim Schreiben oder beim 
Initialisieren liegt.

von MagIO (Gast)


Lesenswert?

Im Tutorial steht aber auch, dass es mit dem Timing bei Takten >= 8MHz 
Probleme geben kann. Deshalb solltest Du beim Schreiben E im Auge 
behalten, damit es nicht zu kurz wird.

Und nach dem schreiben - da du ja nicht liest kann dir das Display auch 
nicht sagen, ob es mit einer Operation fertig ist - musst Du auch ca 
50us warten ... Clear screen z.B. dauert noch länger und man sollte ca. 
5ms warten. Das ist wohl in der Init noch nicht so.

von Masood M. (noob19)


Lesenswert?

habe leider alles versucht. Da stimmt irgendwas nicht.
Ich werde jetzt erstmal pause machen.
Morgen werde ich alles nochmal durchklingeln um zu gucken ob alles 
richtig dran ist und dann versuche ich nochmal mein Glück.

von Darkleon (Gast)


Lesenswert?

Hallo!

Hab mir jetzt das Datenblatt angesehen.

Bei der Init wird eine Pause von mindestens 30ms nach erreichen von VDD 
empfohlen.
In Deinem Code aus dem ersten Post wartest Du nur 15ms.

Das Function Set hast Du richtig initialisiert.
Danach kommt eine Mindestwartezeit von 39us. Die sehe ich in deinem Code 
nicht.

Dann initialisierst Du "Display ON/OFF Control". In dieser 
Initialisation schaltest Du das Display aber aus. Ist doch nicht so 
gewollt, oder?
1
Daten(0,0,0,0);     // ab hier, display aus, blinken aus und cursor aus
2
output_high(E);
3
output_low(E);
4
   
5
Daten(1,0,0,0);
6
output_high(E);
7
output_low(E);     // bis hier
Richtig müsste es laut Datenblatt so sein:
1
Daten(0,0,0,0);    // ab hier, display AN, blinken aus und cursor aus
2
utput_high(E);
3
output_low(E);
4
   
5
Daten(1,1,0,0);
6
output_high(E);
7
output_low(E);    // bis hier

Mindestwartezeit von 39us.

Dann kommt richtigerweise "Display clear".

Mindestwartezeit von 1,53ms.

Dann kommt "Entry Mode Set"
Du sendest DB7 UND DB6 Low, im Datenblatt ist aber DB7 auf Low und DB6 
jeden Fall High.
Danach initialisierst du mit "increment mode"(DB5) und "entire shift 
off"(DB5).
Also Dein Code
1
Daten(0,0,0,0);               // ab hier, kursor nach rechts
2
output_high(E);
3
output_low(E);
4
   
5
Daten(0,0,1,0);
6
output_high(E);
7
output_low(E);                // bis hier
So sollte es aussehen:
1
Daten(0,0,0,0);               // ab hier, kursor nach rechts
2
output_high(E);
3
output_low(E);
4
   
5
Daten(0,1,1,0);
6
output_high(E);
7
output_low(E);                // bis hier

Danach ist die Initialisation zu Ende. Da würd ich auch nochmal ein paar 
ms warten.
Die letzte Init mit dem "Display an..." würd ich weglassen, da das 
Display wahrscheinlich nicht weiß wohin damit. Ich würd das Display 
gleich an richtiger Stelle (wie oben beschrieben) einschalten.

Und warte nach jeder Pegeländerung von E und RS mind. eine us, da du 
laut Datenblatt mit deinen 8Mhz Takt viel zu schnell bist und das 
Display die Pegeländerung nicht korrekt mitbekommt.(Wurde aber schon vor 
diesem Post beschrieben.

Änder mal Deinen Code und Füg die ganzen Wartezeiten hinzu. (Zwischen 
den Initblöcken, bei RS und E und erhöhe die 15ms Wartezeit am Anfang).
Viel kann dann nicht mehr falsch sein.

So long.
Darkleon

von Stephan (Gast)


Lesenswert?

Du musst den ersten Initialisierungsbefehl 3x (!) rüberschicken, danach 
erst auf 4 bit umschalten (siehe http://www.sprut.de/electronic/lcd/), 
bei manchen Displays muss man auch länger warten, also:
1
   delay_ms(15);                     //  15 ! ms warten nach Reset
2
3
   Daten(0,0,1,1);
4
   output_high(E);                     // Befehl an LCD
5
   output_low(E);                     //   (durch toggeln der LCD-Enable-
6
   delay_ms(5);                     //  5 ms warten
7
8
   Daten(0,0,1,1);
9
   output_high(E);                     // Befehl an LCD
10
   output_low(E);                     //   (durch toggeln der LCD-Enable-
11
   delay_ms(1);                     //  1 ms warten
12
13
14
   Daten(0,0,1,1);
15
   output_high(E);                     // Befehl an LCD
16
   output_low(E);                     //   (durch toggeln der LCD-Enable-
17
18
   Daten(0,0,1,0);                   // Auf 4- Bit modus
19
   ...

von Masood M. (noob19)


Lesenswert?

hi,

Danke für deine Zeit und Mühe.

Also ich habe jetzt alles geändert was du sagtest:

hier nochmal falls sich doch fehler reingeschlichen haben:
1
#define RS     PIN_A2
2
#define E      PIN_A3
3
#define DB4    PIN_A6
4
#define DB5    PIN_A7
5
#define DB6    PIN_A0
6
#define DB7    PIN_A1
7
8
void Daten(int a, int b, int c, int d)       //Funktion um 4 Bit Daten über 4 Leiten zu senden
9
{
10
   if (a)
11
   {
12
      output_high(DB7);
13
   }
14
   else 
15
   {
16
      output_low(DB7);
17
   }
18
   if (b)
19
   {
20
      output_high(DB6);
21
   }
22
   else 
23
   {
24
      output_low(DB6);
25
   }
26
   if (c)
27
   {
28
      output_high(DB5);
29
   }
30
   else 
31
   {
32
      output_low(DB5);
33
   }
34
   if (d)
35
   {
36
      output_high(DB4);
37
   }
38
   else 
39
   {
40
      output_low(DB4);
41
   }
42
}
43
44
void LCD_INIT()
45
{
46
   int i;
47
   delay_ms(30);
48
   output_low(RS);                  // Alle LCD-Steuerleitungen LOW
49
   output_low(E);
50
   delay_us(1);   
51
   
52
   for (i=0;i<3;i++)                // Auf das BF warten
53
   {
54
   Daten(0,0,1,1);
55
   output_high(E);                     // Befehl an LCD
56
   delay_us(1);
57
   output_low(E);                     //   (durch toggeln der LCD-Enable-Leitung)
58
   delay_ms(5);                     //  mind. 4.1 ms warten
59
   }
60
   
61
   Daten(0,0,1,0);                   // Auf 4- Bit modus
62
   output_high(E);                  // Befehl an LCD
63
   delay_us(1);
64
   output_low(E);                  //   (durch toggeln der LCD-Enable-Leitung)
65
   
66
   delay_us(40);
67
   
68
   Daten(0,0,1,0);                 //ab hier 2 zeilig und 5x7 Matrix                    
69
   output_high(E);
70
   delay_us(1);
71
   output_low(E);      
72
   
73
   Daten(1,0,0,0);
74
   output_high(E);
75
   delay_us(1);
76
   output_low(E);                // bis hier
77
   
78
   delay_us(40);
79
   
80
   Daten(0,0,0,0);               // ab hier, display AN, blinken aus und cursor aus
81
   output_high(E);
82
   delay_us(1);
83
   output_low(E);
84
   
85
   Daten(1,1,0,0);
86
   output_high(E);
87
   delay_us(1);
88
   output_low(E);                // bis hier
89
   
90
   delay_us(40);
91
   
92
   Daten(0,0,0,0);               // ab hier, display clear
93
   output_high(E);
94
   delay_us(1);
95
   output_low(E);
96
   
97
   Daten(0,0,0,1);
98
   output_high(E);
99
   delay_us(1);
100
   output_low(E);                // bis hier
101
   
102
   delay_ms(2);
103
104
   Daten(0,0,0,0);               // ab hier, kursor nach rechts
105
   output_high(E);
106
   delay_us(1);
107
   output_low(E);
108
   
109
   Daten(0,1,1,0);
110
   output_high(E);
111
   delay_us(1);
112
   output_low(E);                // bis hier
113
 
114
   delay_ms(5);
115
}
116
117
void LCD_SCHREIBEN()
118
{
119
   output_high(RS);                  // rs high um zu schreiben
120
   delay_us(1);
121
   output_low(E);
122
   
123
   Daten(0,0,1,1);               // die ersten 4 bit
124
   output_high(E);
125
   delay_us(1);
126
   output_low(E);
127
   
128
   Daten(0,0,0,1);               // die letzen 4 bit
129
   output_high(E);
130
   delay_us(1);
131
   output_low(E);                
132
   
133
   delay_us(1);
134
   output_low(RS);
135
}



Leider kein Erfolg.
Die untere Zeile leuchtet komplett schwarz auf.
Ich werde morgen nochmal alles durchklingeln und schauen.
Ich hoffe dass nur da der Fehler ist und es nicht am Programm liegt.

von holger (Gast)


Lesenswert?

>Die untere Zeile leuchtet komplett schwarz auf.

Das ist die OBERE Zeile ;)

von Masood M. (noob19)


Lesenswert?

@ Stephan : mit meiner for-schleife schicke ich das ganze 3 mal rüber.

von Masood M. (noob19)


Lesenswert?

@ holger, wenn das die Obere zeile ist, dann weiß ich wo der Fehler 
liegt ... :P

THX

von MagIO (Gast)


Lesenswert?

;o)))


die kleine 1 übersehen

von Darkleon (Gast)


Lesenswert?

Wie ist der momentane Status?

Funktioniert es jetzt?
Deinem Code entnehme ich folgende Pinbelegung:
RS  -- RA2
E   -- RA3
DB4 -- RA6
DB5 -- RA7
DB6 -- RA0
DB7 -- RA1

Im Datenblatt des PICs steht unter "5.0 I/O Ports", dass bei einem Reset 
die Pins RA0 - RA4 als digitale Inputs konfiguiert sind.
Da du diese Pins für dein LCD als digitale Outputpins benötigst, musst 
du dies natürlich dem Controller in das ADCON1 Register schreiben. Sonst 
bleiben diese Pins analoge Inputs.

Ich weiß ja nicht, welchen Compiler du verwendest?! Macht der das 
automatisch? Denke nicht.
Daher musst Du das ADCON1 Register mit dem Wert 0x06 beschreiben.
So werden die Pins RA0 - RA4 als digitale Pins definiert!

Denke an dem wirds liegen (sofern Du nichts falsch vedrahtet hast), denn 
die Initialisierung stimmt soweit. Auch das Senden der Daten (In Deinem 
Fall die Zahl eins!)

Melde Dich, sobald Du das überprüft hast. Würd mich interessieren.

So long,
Darkleon

von Darkleon (Gast)


Lesenswert?

Update:

Meinte natürlich, dass RA0 - RA4 ANALOGE und nicht digitale Inputs bei 
einem Reset (und auch standarmäßig) Pins sind.

Die Hand war wieder schneller als das Hirn ;)

Gibts schon Neuigkeiten?

MfG Darkleon

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.