Guten Morgen allerseits,
ich versuche schon seit 3 Wochen ein LCD Display (Typ: Dot-matrix LCD
204B-LED, Datenblatt s. Anhang) mittels eines AT89C5131 anzusteueren.
Ich scheitere jedoch schon an der Initialisierung, obwohl ich das
AVR-LCD Tutorial von mikrocontroller.net beinahe Auswendig kenne, und
ich alle Schritte von der Beispielinitialisierung in mein Programm
übernommen habe.
Ich weiß auch das die Zeit das A und O bei der Initialisierung ist, ich
habe jedoch ausreichend große Wartefunktionen eingebaut, der Timer an
sich läuft auch, trotzdem will es mit der Inititalisrung nicht klappen
:/
Langsam stoße ich an meine Grenzen, ich bitte daher um eure Hilfe!
Vorneweg: Am µC liegt es nicht, dieser funktioniert eiwandfrei bei
anderen Programmen.
Hier ist der Code:
Ronny S. schrieb:> Hallo,> schau Dir das mal an und Teste es dann mal.>> http://homepage.hispeed.ch/peterfleury/avr-software.html#libs>> LCD library for HD44870 based LCD's>> Gruß Ronny
Zuerst einmal Vielen Dank für deine Antwort.
Allerdings solltest du dir auch mein Programm anschauen, denn ich gehe
genau so vor wie in dem Tutorial auf der Seite beschrieben. Das Programm
dort kann ich nicht verwenden, da ich Keil µVision 4 als Compiler
benutze und der AT89C5131 auch ganz anders anzusteuern ist als der dort
verwendete Controller.
Der AT89... ist einer der am einfachsten anzusteuernden Controller, wie
man an meinem Programm sieht.
Versteht mich nicht falsch, ich suche hier keinen der mir meine Arbeit
abnimmt und eine fertige Init für meinen Controller schreibt, ich suche
einfach nur jemanden der Erfahrung mit dem AT89... hat und sich mein
Programm anschaut und mir einen Denkanstoß gibt, wo der Fehler sein
könnte.
Ich habe nämlich mittlerweile das halbe Internet nach LCD-Inits in C
durchforscht und so ziemlich alles ausprobiert, was ich dort gelesen
habe. Nichts hat geholfen, deshalb bin ich so langsam mit meinem Latein
am Ende
Was mir so auf die Schnelle(tm) auffällt:
1) du verwendest als Parameter char -> bist sicher dass es automatisch
ein unsigned char ist (bei char ist das ggf. Compiler-abhängig, bei int
i.d.R. ohne Angabe = signed) ?
2) du verwendest als Parameter int -> warum 16-bit für eine 8-bit
Operation?
3) du verwendest als Parameter int -> das dürfte definitiv mit
Vorzeichen sein.
Ralf
Sascha H. schrieb:> lcd_out(01000011); // ASCII = "C"Der Kommentar sollte immer zum Code passen!
lcd_out ???
01000011 = 0x40009 = 262153
Sascha H. schrieb:> TH0 = 0xFF; //High-Byte 0b11111111> TL0 = 0x9B; //Low-Byte 0b11111110Der Kommentar sollte immer zum Code passen!
Seit wann ist 0x9B == 0b11111110 ?
Man kann es auch leserlich schreiben, dann ist ein Kommentar
überflüssig:
1
#define hi(x) ((x)>>8)
2
#define lo(x) ((x)&0xFF)
3
4
TH0=hi(-100);
5
TL0=lo(-100);
Dein Delay ist also bei 12MHz: zeit * 100µs
Sascha H. schrieb:> static void lcd_enable( void )> {> P1_2 = 1;> wait (200); // 100µS Warten> P1_2 = 0;> wait (200);> }Der Kommentar sollte immer zum Code passen!
Du wartest nämlich 20ms.
Du kannst dem Datenblatt ruhig glauben, wenn da steht, daß 500ns
reichen.
Bernd N schrieb:> Laut Datenblatt...>> cursor_off 0x0C> cursor_blink 0x0D> cursor_on 0x0E> clear_display 0x01> cursor_home 0x02> entry_mode 0x38>> Also z.B. Init 3x 0x38, Cursor OFF, Clear Display, Cursor Home
Vielen, vielen Dank, damit hat es geklappt!
Allerdings ist mir nicht ersichtlich wo du diese Werte hernimmst? Im
Initialisierungsbeispiel im DB steht für 8 Bit folgende Reihenfolge und
Werte:
1x Function Set 0x1C
1x Disp ON/OFF 0xF0
1x Clear Display 0x80
1x Entry Mode Set 0x60
__________________________________________
@ Ralf
Danke für deinen Tipp mit den Variablen, in der Schule haben wir fast
nur mit Integer gearbeitet deswegen ist es eine Standard-Variable bei
mir geworden, da habe ich noch garnicht daran gedacht.
___________________________________________
@ peda
Tut mir leid dass nicht alle Kommentare zum Code passen, durch das viele
herumprobieren in den letzten Wochen ist da einiges durcheinander
geraten.
____________________________________________________
Jetzt fehlt mir nur noch ein Zeichen auf dem Display auszugeben...
Ich wollte ein einfaches "C" darstellen, in ASCII "C" -> 0b01000010 =
0x42
Dieses habe ich dann einfach an Port 2 gesendet und danach die
Enable-Funktion aufgerufen, trd klappt dies nicht. Gibt es da etwas zu
beachten?
Hi
>Allerdings ist mir nicht ersichtlich wo du diese Werte hernimmst? Im>Initialisierungsbeispiel im DB steht für 8 Bit folgende Reihenfolge und>Werte:>1x Function Set 0x1C>1x Disp ON/OFF 0xF0>1x Clear Display 0x80>1x Entry Mode Set 0x60
Du musst die Binärwerte in der richtigen Reihenfolge lesen:
Function set 0 0 1 1 1 0 0 0
3 8
>Dieses habe ich dann einfach an Port 2 gesendet und danach die>Enable-Funktion aufgerufen, trd klappt dies nicht. Gibt es da etwas zu>beachten?
Um ein Zeichen zu schreiben muss auch RS auf 1 gesetzt werden.
MfG Spess
spess53 schrieb:> Du musst die Binärwerte in der richtigen Reihenfolge lesen:>> Function set 0 0 1 1 1 0 0 0> 3 8>
Aber ich habe an P2_0 doch DB0 und an P2_7 DB7 anliegen, also ist die
Reihenfolge doch eig andersherum als im Datenblatt oder?
Zudem sind im Datenblatt als Init.-Beispiel auch andere Funktionen
angegeben als die, die Bernd N. hier angegeben hat.
Init.-Beispiel aus Datenblatt:
1x Function Set 0x1C
1x Disp ON/OFF 0xF0
1x Clear Display 0x80
1x Entry Mode Set 0x60
> Um ein Zeichen zu schreiben muss auch RS auf 1 gesetzt werden.
Vielen Dank, es klappt nun!
Hi
>Aber ich habe an P2_0 doch DB0 und an P2_7 DB7 anliegen, also ist die>Reihenfolge doch eig andersherum als im Datenblatt oder?
Nein. In einer Binärzahl steht das höherwertigste Bit immer links:
P2_7 P2_6 P2_5 P2_4 P2_3 P2_2 P2_1 P2_0
DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 1 1 1 0 0 0
3 8
MfG Spess
Guten Morgen Sascha,
> Allerdings ist mir nicht ersichtlich wo du diese Werte hernimmst? Im> Initialisierungsbeispiel im DB steht für 8 Bit folgende Reihenfolge und> Werte:>> 1x Function Set 0x1C> 1x Disp ON/OFF 0xF0> 1x Clear Display 0x80> 1x Entry Mode Set 0x60
Falsch, uns ist nämlich nicht ersichtlich woher DU DEINE Werte
hernimmst. Wenn du dir das DB nochmal anguckst wirst du sehen, dass da
1x Function Set 0x1C (korrekt)
1x Disp ON/OFF 0xF0 (falsch) -> 0x0F
1x Clear Display 0x80 (falsch) -> 0x01
1x Entry Mode Set 0x60 (falsch) -> 0x06
steht.
Allerdings steht im DB ja auch beispielsweise, dass 0x0F nicht nur Disp
ON (nicht OFF!!!) ist, sondern gleichzeitig auch blinkender Cursor ist -
du siehst also, es kommt auf die einzelnen Bits an.
Deswegen halte ich das:
> cursor_off 0x0C> cursor_blink 0x0D> cursor_on 0x0E
für falsch. M.E. müsste es so sein:
cursor_off 0x00
cursor_on 0x02
cursor_blink 0x01
cursor_static 0x00
display_on 0x04
display_off 0x00
display_ctrl 0x08
Den Aufruf macht man dann durch eine Veroderung der Parameter:
lcdcmd(display_ctrl | cursor_on | display_on);
> Danke für deinen Tipp mit den Variablen, in der Schule haben wir fast> nur mit Integer gearbeitet deswegen ist es eine Standard-Variable bei> mir geworden, da habe ich noch garnicht daran gedacht.
Mmmmh.... vergiss bitte den Stuss aus der Schule - vorne am Pult sitzt
auch nur einer, der das amateurhaft macht und dir vielleicht erzählen
kann wie man ein MCU-Board und zugehörige IDE in Betrieb nimmt. Und
falls ihr in der Schule nur Programme für den PC gemacht habt isses
nochmal anders als für Controller (da ist das mit "immer nur int" nicht
ganz so schlimm).
Faktisch gelten für's erste(!) folgende Regeln:
1) generell den Variablentyp entsprechend der Architektur wählen -> also
8-bit/char für z.B. 8051er 8-bit MCU (so wie du einen hast) und 32-bit
für einen ARM 32-bit MCU. Das macht man, weil der Controller bzw.
Compiler dann nicht erst Befehle generieren muss, um das passend zu
behandeln. Kleines Beispiel: ein 8051 (8-bit MCU) soll einen int
(16-bit) verarbeiten. Als 8-Bitter kann er aber nur 8-bit Rechnungen
durchführen, für einen int muss er also mehrere 8-Bit-Befehle ausführen.
Umgekehrt kann für einen 32-Bitter eine char-Variable (8-Bit) ein
kleines Problem sein, wenn aus dem RAM nur 32-Bit am Stück gelesen
werden können: dann müssen die relevanten acht Bit maskiert werden, dann
die Berechnung, und dann wieder zurück schreiben, ohne die anderen 24
Bits zu beeinflussen.
2) immer den Variablentyp entsprechend der Aufgabe wählen -> wenn du nur
einen Zähler für sagen wir zehn Schleifendurchläufe benötigst, brauchst
du weder einen int noch einen long - da tut's ein char -> Begründung
siehe 1).
3) wenn Variablen keinen negativen Bereich benötigen, dann immer
unsigned anlegen. Die meisten Controller benötigen für Rechnungen mit
Vorzeichen zusätzlichen Aufwand, d.h. es wirkt sich ggf. auf die
Laufzeit aus.
So, und wie passt nun 2) zu 1), wenn man "RAM-sparend" programmieren
muss? Auf nem 32-Bitter wählst du für globale Variablen den nötigen Typ
(siehe 2). In Funktionen legst du lokale Variablen für Schleifen etc.
nach 1) an. Der Speicher der lokalen Variablen steht nach der Funktion
ja wieder zur Verfügung, daher bietet es sich eben an, den Typ zu
wählen, mit dem am schnellsten gearbeitet werden kann.
> Tut mir leid dass nicht alle Kommentare zum Code passen, durch das viele> herumprobieren in den letzten Wochen ist da einiges durcheinander> geraten.
Was Peter sagen wollte ist einfach, dass Kommentare kein notwendiges
Übel, sondern auch ein Hilfsmittel für den Programmierer sind. Viele
lassen die Kommentare ganz weg und checken zwei Tage später nicht mehr,
was sie da gemacht haben.
Richtig angewandt helfen sie dir sogar Fehler zu entdecken. Du hast ja
bei Peter gesehen, dass er sofort Unterschiede zwischen Kommentar und
Befehl erkannt hat.
> Jetzt fehlt mir nur noch ein Zeichen auf dem Display auszugeben...> Ich wollte ein einfaches "C" darstellen, in ASCII "C" -> 0b01000010 => 0x42> Dieses habe ich dann einfach an Port 2 gesendet und danach die> Enable-Funktion aufgerufen, trd klappt dies nicht. Gibt es da etwas zu> beachten?
Ein ASCII-"C" ist 0x43, wenn ich mich recht entsinne ;)
Wie hast du das Zeichen geschickt? Denk dran, dass du in dem Fall nicht
ein Kommando, sondern Daten schicken willst, das heisst du musst RS
passend bedienen...
Ralf
Vielen, vielen Dank für eure Antworten, es klappt nun mittlerweile alles
wie gewollt und dank eurer teils sehr ausführlichen Antworten habe ich
auch einiges dazu gelernt.
Finde ich gut dass hier einem geholfen wird, obwohl ein Thema wie
Display-Initialisierung hier schon 100000x durchgekaut wurde und es den
meisten Usern zum Halse raushängen dürfte.
Genau deshalb ein dickes Dankeschön an alle die mir geholfen haben!
Schönen Tag wünsche ich euch noch ;-)
______________________________________________________________________
CLOSED