www.mikrocontroller.net

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


Autor: Masood M. (noob19)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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;GRO...

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.

Autor: Darkleon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Was mir sofort bei deinem Code aufgefallen ist ist folgendes:
void main()
{
while (1)
{
   LCD_INIT();
   LCD_SCHREIBEN();

}
}
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.
void main()
{
   LCD_INIT();
   LCD_SCHREIBEN();
while (1)
{
Nop();
}
}

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

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Darkleon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: MagIO (Gast)
Datum:

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

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Darkleon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
Daten(0,0,0,0);     // ab hier, display aus, blinken aus und cursor aus
output_high(E);
output_low(E);
   
Daten(1,0,0,0);
output_high(E);
output_low(E);     // bis hier
Richtig müsste es laut Datenblatt so sein:
Daten(0,0,0,0);    // ab hier, display AN, blinken aus und cursor aus
utput_high(E);
output_low(E);
   
Daten(1,1,0,0);
output_high(E);
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
Daten(0,0,0,0);               // ab hier, kursor nach rechts
output_high(E);
output_low(E);
   
Daten(0,0,1,0);
output_high(E);
output_low(E);                // bis hier
So sollte es aussehen:
Daten(0,0,0,0);               // ab hier, kursor nach rechts
output_high(E);
output_low(E);
   
Daten(0,1,1,0);
output_high(E);
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

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
   delay_ms(15);                     //  15 ! ms warten nach Reset

   Daten(0,0,1,1);
   output_high(E);                     // Befehl an LCD
   output_low(E);                     //   (durch toggeln der LCD-Enable-
   delay_ms(5);                     //  5 ms warten

   Daten(0,0,1,1);
   output_high(E);                     // Befehl an LCD
   output_low(E);                     //   (durch toggeln der LCD-Enable-
   delay_ms(1);                     //  1 ms warten


   Daten(0,0,1,1);
   output_high(E);                     // Befehl an LCD
   output_low(E);                     //   (durch toggeln der LCD-Enable-

   Daten(0,0,1,0);                   // Auf 4- Bit modus
   ...

Autor: Masood M. (noob19)
Datum:

Bewertung
0 lesenswert
nicht 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:

#define RS     PIN_A2
#define E      PIN_A3
#define DB4    PIN_A6
#define DB5    PIN_A7
#define DB6    PIN_A0
#define DB7    PIN_A1

void Daten(int a, int b, int c, int d)       //Funktion um 4 Bit Daten über 4 Leiten zu senden
{
   if (a)
   {
      output_high(DB7);
   }
   else 
   {
      output_low(DB7);
   }
   if (b)
   {
      output_high(DB6);
   }
   else 
   {
      output_low(DB6);
   }
   if (c)
   {
      output_high(DB5);
   }
   else 
   {
      output_low(DB5);
   }
   if (d)
   {
      output_high(DB4);
   }
   else 
   {
      output_low(DB4);
   }
}

void LCD_INIT()
{
   int i;
   delay_ms(30);
   output_low(RS);                  // Alle LCD-Steuerleitungen LOW
   output_low(E);
   delay_us(1);   
   
   for (i=0;i<3;i++)                // Auf das BF warten
   {
   Daten(0,0,1,1);
   output_high(E);                     // Befehl an LCD
   delay_us(1);
   output_low(E);                     //   (durch toggeln der LCD-Enable-Leitung)
   delay_ms(5);                     //  mind. 4.1 ms warten
   }
   
   Daten(0,0,1,0);                   // Auf 4- Bit modus
   output_high(E);                  // Befehl an LCD
   delay_us(1);
   output_low(E);                  //   (durch toggeln der LCD-Enable-Leitung)
   
   delay_us(40);
   
   Daten(0,0,1,0);                 //ab hier 2 zeilig und 5x7 Matrix                    
   output_high(E);
   delay_us(1);
   output_low(E);      
   
   Daten(1,0,0,0);
   output_high(E);
   delay_us(1);
   output_low(E);                // bis hier
   
   delay_us(40);
   
   Daten(0,0,0,0);               // ab hier, display AN, blinken aus und cursor aus
   output_high(E);
   delay_us(1);
   output_low(E);
   
   Daten(1,1,0,0);
   output_high(E);
   delay_us(1);
   output_low(E);                // bis hier
   
   delay_us(40);
   
   Daten(0,0,0,0);               // ab hier, display clear
   output_high(E);
   delay_us(1);
   output_low(E);
   
   Daten(0,0,0,1);
   output_high(E);
   delay_us(1);
   output_low(E);                // bis hier
   
   delay_ms(2);

   Daten(0,0,0,0);               // ab hier, kursor nach rechts
   output_high(E);
   delay_us(1);
   output_low(E);
   
   Daten(0,1,1,0);
   output_high(E);
   delay_us(1);
   output_low(E);                // bis hier
 
   delay_ms(5);
}

void LCD_SCHREIBEN()
{
   output_high(RS);                  // rs high um zu schreiben
   delay_us(1);
   output_low(E);
   
   Daten(0,0,1,1);               // die ersten 4 bit
   output_high(E);
   delay_us(1);
   output_low(E);
   
   Daten(0,0,0,1);               // die letzen 4 bit
   output_high(E);
   delay_us(1);
   output_low(E);                
   
   delay_us(1);
   output_low(RS);
}



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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Die untere Zeile leuchtet komplett schwarz auf.

Das ist die OBERE Zeile ;)

Autor: Masood M. (noob19)
Datum:

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

Autor: Masood M. (noob19)
Datum:

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

THX

Autor: MagIO (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;o)))


die kleine 1 übersehen

Autor: Darkleon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Darkleon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.