Forum: Mikrocontroller und Digitale Elektronik mal wieder EA DIP204 LCD mit KS0073


von Marcel K. (viewer)


Lesenswert?

Hallo Forumgemeinde,
also ich versuche jetzt seit 2 Tagen mein Display anzusteuern. Ich weiß 
dass es funktioniert da ich es mit CodeVision bereits angesteuert habe.
Ich arbeite aber auch ab und zu mit einer anderen Software (IAR). Also 
muss ich eine eigene C- Datei schreiben. Ich sehe dass natürlich auch 
mal als eine gute Übung da ich nicht wirklich der Programmierprofi bin.
Ich bekomme das aber irgendwie nicht richtig hin da mir einiges an 
Grundwissen fehlt. Ich habe das PDF für den KS0073 gelesen. Darin steht 
für den 4 Bit Mode: (S.59)

Function Mode: 0x20

Das verstehe ich ja noch da ja mit dem DB4 = 0 in den 4 Bit Mode 
gewechselt wird. Im Beispiel wird aber nur ein Nibbel gesendet, wie so 
dass den?? Sonst benötige ich doch immer 2 Nibbel. Wie weiß den das 
Display das jetzt noch ein Nibbel kommt oder nicht??

Mein Quellcode sieht so aus:



/////// lcd.h/////////////
#define LCD PORTC
#define LCD_D DDRC

#define RS       0 // Bit[0] --> Umschalten zwischen:
                                 Befehl(Low) und Daten (High)
#define RW       1 // Bit[1] --> Unschalten zwischen:
                                 Write (Low) und Read (High)
#define EN       2 // Bit[2] --> Enable bei fallender Flanke

void pause(int zaehler)
{
  int temp=zaehler;
  while(temp>0)
  {
    asm ("nop");
    asm ("nop");
    temp--;
  }
}

void toggel_en()
{
  pause(10000);
  LCD|=(1<<EN);   //RS Pin auf High
  pause(10000);
  LCD&=~(1<<EN);  //RS Pin auf Low
  pause(10000);
}

void send_to_lcd(U8 daten)
{
  LCD = (daten&0xf0);   // das erste Nibbel der Daten
                           auf die 4 Datenleitungen legen
  toggel_en();          // EN "toggeln" --> high / low
  LCD = (daten<<4);     // das zweite Nibbel der Daten
                           auf die 4 Datenleitungen legen
  toggel_en();          // EN "toggeln" --> high / low
}


lcd_init()
{
  pause(20000); // länger Zeit warten


  //Port A als Ausgang
  LCD_D=0xff;
  LCD=0x00;

  LCD &= ~  (1<<RS);  // RS auf low
  LCD &= ~  (1<<RW);  // RW auf low


  send_to_lcd(0x20);  // schaltet in den 4 Bit Modus
  pause(20000);       // länger Zeit warten
  send_to_lcd(0x24);  // RE = 1
  send_to_lcd(0x0B);  // 5 DOT, normal cursor, 4 Lines
  send_to_lcd(0x20);  // RE = 0
  send_to_lcd(0x0F);  // Display, Cursor, blink = 1
  send_to_lcd(0x01);  // clear Display
  pause(20000);       // länger Zeit warten
  send_to_lcd(0x06);  // Entry-Mode
  send_to_lcd(0x02);  // Cursor @ Home
}

////////////// in der Main /////////////////

#include "lcd.h"

void main(void)
{
  WDT_off();
  uart_init();
  lcd_init();

  while (1)
  {


  }

}


Auf dem Display passiert aber leider nichts :o( Kein Cursor oder 
sonstiges ist zu sehen.
Wie gesagt, ich weiß dass das Display funktioniert. Ich kann es mit 
CodeVision ansteuern. Was mach ich den falsch?? Ist die Initialisierung 
so richtig??
Ich würde mich über eine Antwort wirklich sehr freuen!!

Schönen Sonntag noch,

Grüße Marcel

von Matthias (Gast)


Lesenswert?

vielleicht hilft das weiter:
Beitrag "LCD EA DIP204 KS0073 4-Bit, 8-Bit und serielle C-Routinen"
(DIP-204 Ansteuerung in C für alle 3 Varianten 4/8/SPI-Mode, jedoch für 
8051-Familie, lässt aber leicht portieren)

von Max (Gast)


Lesenswert?

>send_to_lcd(0x20);  // schaltet in den 4 Bit Modus
>pause(20000);       // länger Zeit warten

Die erste 0010 musst Du alleine senden, nicht mit mit 2 Hablbytes. Dazu 
kannst Du Deine send_to_lcd nicht verwenden.

Dann fragst Du auch nirgens das BUSY-Flag ab. Außerdem musst Du beim 
KS0073 eine Zykluszeit zwischen 2 Sequenzen einhalten, auch zwischen den 
2 Nibbles.

Tschau Max

von Marcel K. (viewer)


Lesenswert?

@ Max,

danke erst mal für deine Antwort. Hmmm, das Busy-Flag!! Da habe ich mal 
eine Funktion geschrieben:

///////////////// ausschnitt aus dem Programm: (habe jetzt eine .c Datei 
daraus gemacht!!!

#include "uart.h"
#include "lcd_test.h"

#define LCD PORTC
#define LCD_D DDRC
#define LCD_PIN PINC
#define RS        0 // Bit[0] --> Umschalten zwischen:
                                  Befehl(Low) und Daten (High)
#define RW        1 // Bit[1] --> Unschalten zwischen:
                                  Write (Low) und Read (High)
#define EN        2 // Bit[2] --> Enable bei fallender Flanke
#define BF        7 // Bit[7] --> Busy Flag am Display



busy_flag()
{
  LCD&=~(1<<RS);        // RS auf Low
  LCD|=(1<<RW);         // RW auf High
  toggel_en();          // EN "toggeln" --> high / low

  while ( !(LCD_PIN & (1<< BF)) )
  {
    uart_putchar('B');
  };

  LCD&=~(1<<RW);  //RW auf Low
}



das Bit wird aber nie gesetzt!! (endlos-schleife) Was mach ich den schon 
wieder falsch??
Ich sehe schon, das sieht nach großer Verzweifelung aus. Ab wann kann 
man das Busy-Flag abfragen? noch vor der Init??

Was meinst du mit:
"eine Zykluszeit zwischen 2 Sequenzen"??
In toggel warte ich doch eine ganze weile bis ich wieder weiter 
schreiben??

Danke für eure Bemühungen!!!!

von Marcel K. (viewer)


Lesenswert?

Ich habe meine Funktion Busy noch mal umgeschrieben:

busy_flag()
{
  U8 sperre = 1;
  LCD&=~(1<<RS);      //RS auf Low
  LCD|=(1<<RW);        //RW auf High
  LCD|=(1<<EN);        //EN auf High
  pause(100);

  while ( !(sperre ) )
  {
     LCD|=(1<<EN);    //EN auf High
     pause(100);
     LCD&=~(1<<EN);   //EN auf Low
     pause(100);

     if(!(LCD_PIN & (1<< BF)))
     {
       sperre = 0;
     }

     LCD|=(1<<EN);    //EN auf High
     pause(100);
     LCD&=~(1<<EN);   //EN auf Low
     pause(100);

     uart_putchar('B');
  };

  LCD&=~(1<<RW);  //RW auf Low
}

geht aber immer noch nicht!!

von Matthias (Gast)


Lesenswert?

Bei HD44780 darf man das BUSY-Flag erst nach der Erstinitialisierung 
abfragen. Bei KS0073 soweit ich weiß, geht das sofort. 4 Bit 
Initialisierung ist bei KS0073 eigentlich einfach, nur das erste 0010 
muß einzeln gesendet werden. In manchen Fällen kommt es dadurch aber zu 
Problemen, z.B. wenn Du das Programm durch einen Reset startest, von dem 
der KS0073 aber nichts mitbekommt. Versuchs auch mal durch 
aus/einschalten.

Andere Frage:
Wie hast Du den RESET-PIN gesetzt und hast Du den Kontrast richtig 
eingestellt?

von Marcel K. (viewer)


Lesenswert?

@ Matthias,
danke für deine Antwort!!
Also ich habe den Reset-Pin gar nicht belegt, der hängt frei rum !!! 
Muss man den zwingend belegen?? Der Kontrast ist aber OK. Nach vielen 
Stunden habe ich es bereits hin bekommen das ich das LCD sauber 
initialisieren kann. Auch das positionieren des Cursors funktioniert 
ohne Probleme.
Jetzt kommen die nächsten Probleme :o(

Ich möchte auf das Dispalay einfach nur ein Zeichen schreiben aber das 
klappt natürlich nicht!!! (wieso auch......)


die Funktionen:

void toggel_en()
{
  pause(10000);
  //busy_flag();
  LCD|=(1<<EN);    //EN auf High
  pause(10000);
  LCD&=~(1<<EN);  //EN auf Low
  pause(10000);
}

void send_to_lcd(U8 byte)
{
  LCD = (byte&0xf0);        // das erste Nibbel an die Pins anlegen
  toggel_en();              // EN "toggeln" --> high / low
  LCD = (byte<<4);      // das zweite Nibbel an die Pins anlegen
  toggel_en();              // EN "toggeln" --> high / low
}

void send_data(U8 byte)
{
  LCD |=    (1<<RS);        // generell mal RS Pin auf High
  LCD &= ~  (1<<RW);        // generell mal RW Pin auf low
  send_to_lcd(byte);
}

void lcd_putchar(U8 signe)
{
  send_data(signe);
}


Der Funktionsaufruf in main:

lcd_putchar(0x41);

Ich habe ja einige Programmbeispiele im Netz gefunden aber bei jedem ist 
es irgendwie gleich. Ich weiß nicht wo der Fehler ist!! Ich habe die 
Vermutung dass ich irgend etwas vergessen habe einzustellen oder zu 
initialisieren, nur weiß ich nicht was. Muss man noch irgendwelche 
Scroll-Funktionen aktivieren???
Wäre über einen hilfreichen Hinweis sehr dankbar!!

Grüße, Marcel

von Matthias (Gast)


Lesenswert?

>Also ich habe den Reset-Pin gar nicht belegt, der hängt frei rum !!!
>Muss man den zwingend belegen??
Nicht zwingend, aber sinnvoll RESET-Pin mit in den System-Restkreis 
aufzunehmen, ggf. einen Portpin opfern. Überlegung wäre, gleich das 
Display im SPI/seriellen Mode zu betreiben...

>Stunden habe ich es bereits hin bekommen das ich das LCD sauber
>initialisieren kann. Auch das positionieren des Cursors funktioniert
>ohne Probleme.

Schon mal ein Anfang, Steuerzeichen senden dürfte ok sein. Nun scheint 
das Problem beim Daten senden zu liegen. Auf Anhieb sehe ich keinen 
Fehler, hast Du mal die Lcd_Init mit anderen Parametern probiert, wie im 
EA Dip-204 Datenblatt?

Wie groß ist pause(10000) in realer Zeit?

von Marcel K. (viewer)


Lesenswert?

@ Matthias,
danke für die Antwort!!!
Gerade eben habe ich etwas gefunden!!

Also ich schreibe in der main:

lcd_gotoxy(4,3);    // zufällig irgend wo hin springen
lcd_putchar(0x41);  // Zeichen ausgeben

Jetzt ist mein Cursor an die Stelle gesprungen und dann zwei stellen 
zurück. Am Anfang dachte ich das da irgend etwas mit dem scrollen nicht 
stimmt und das Display einfach in die falsche Richtung schreibt.

ABER!!!! wie es der Zufall will, ist die Adresse 0x41 genau X=2, Y=3.

Jetzt denke ich mal das ich mit putchar(0x41) an die stelle springe und 
nicht dem display sage, er soll den wert anzeigen. Aber wie sage ich ihm 
das denn??
Hat das etwas mit den SEG-Ram zu tun???

Schönen Abend noch!!!

von Matthias (Gast)


Lesenswert?

... ob Daten oder Steuerzeichen übertragen werden wird mit RS 
festgelegt.

RS = 1 Daten
RS = 0 Steuerzeichen

dann prüfe mal ob RS auch wirklich richtig gesetzt wird...

von Marcel K. (viewer)


Lesenswert?

Mir fehlen tatzächlich die 5V an dem Pin!!!
Kann es sein das es daran liegt das die Datenleitung und RS am gleichen 
Port hängen?? Da gibt es doch Probleme:

void send_to_lcd(U8 byte)
{
  LCD = (byte&0xf0);        // das erste Nibbel an die Pins anlegen
  toggel_en();              // EN "toggeln" --> high / low
  //LCD = (byte<<4);      // das zweite Nibbel an die Pins anlegen
  byte = byte<<4;
  LCD = (byte&0xf0);
  toggel_en();              // EN "toggeln" --> high / low
}
oder sehe ich das falsch??

Wird bei LCD wirklich nur die obersten Bits geändert??

Grüße

von Marcel K. (viewer)


Lesenswert?

Ja genau, das war der Fehler!!

Durch den Befehl: byte<<4 werden das untere Nibbel mit 0000 gefüllt und 
somit steht dann auch an RS = 0!!

Danke für die Hilfe!!!

Schönen Abend noch und Grüße,

Marcel

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.