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
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)
>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
@ 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!!!!
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!!
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?
@ 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
>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?
@ 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!!!
... 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...
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.