Hallo zusammen,
da ich keinen richtigen Beispielcode für das Ansteuern eines LCD
Displays über einen ATmega16 gefunden habe, habe ich diesen Beitrag
erstellt. Ich habe einen LCD Displaytech 204B an den PORTA meines
ATmega16 angeschlossen, so wie es im Datenblatt des LCD Displaytech 204B
stand. Dort steht auch welche Ports ich schalten muss um ein bestimmtes
Symbol auf den LCD zu bekommen. Da ich jedoch noch keine Erfahrungen mit
LCD Displays habe, wollte ich euch um einen Beispielcode bitten, der
irgend ein Zeichen auf den Bildschirm zaubert. Datenblatt habe ich
angehangen.
Danke schonmal im voraus,
Tobias
Tobias Neumann schrieb:> Hallo zusammen,> da ich keinen richtigen Beispielcode für das Ansteuern eines LCD> Displays über einen ATmega16 gefunden habe, habe ich diesen Beitrag> erstellt.
Für dein spezifisches LCD wirdsich wahrscheinlich nicht allzuviel
finden. Aber für Standard-LCD findet sich jede Menge.
Dein Controller auf dem LCD ist ein KS0063B und so wie ich das auf die
Schnelle sehe, funktioniert der sehr ähnlich einem HD7445.
> Ich habe einen LCD Displaytech 204B an den PORTA meines> ATmega16 angeschlossen, so wie es im Datenblatt des LCD Displaytech 204B> stand.
Was genau hast du wo angehängt. Ich glaube kaum, dass im Datenblatt
exakt steht, welchen LCD Anschluss du an welchen Pin von deinem Port A
angeschlossen hast.
> Symbol auf den LCD zu bekommen. Da ich jedoch noch keine Erfahrungen mit> LCD Displays habe, wollte ich euch um einen Beispielcode bitten, der> irgend ein Zeichen auf den Bildschirm zaubert.
Studiere die LCD Abschnitte in den Tutorials
http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCDhttp://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
Auch wenn dein LCD nicht 100% identisch ist zu den dort gezeigten, ist
es doch ähnlich genug, dass dieselben Prinzipien gehen.
Hallo,
ich schreibe kurz nieder was ich wo angeschlossen habe:
VSS -> GND
VDD -> 5V
VO -> nicht angeschlossen
RS -> PD5
R/W -> PD6
E -> PD7
DB0-DB7 -> PA0-PA7
A -> nicht angeschlossen
K -> nicht angeschlossen
Ich lese mir mal die Tutorials durch und hoffe daraus schlauer zu
werden.. danke schonmal :)
Tobias Neumann schrieb:> Das Problem ist das ich den Controller in C programmiere und mit den> Codebeispielen nicht anfangen kann.. =/
1) Im AVR-GCC-Tutorialsind die Codebeispiele in C
2) Wenn du nichts weiter tun willst als Codebeispiele abtippen ohne
verstehen zu wollen was da passiert, ok, dann versteh ich, dass
dich der Link ins Assemblerbeispiel nicht weiterbringt.
Andere lesen sich den trotzdem durch und holen sich aus dem Text
Informationen raus, die so nicht oder in anderer Formulierung
im C-Tutorial stehen.
Auf die Art ergänzen sich manchmal mehrere Tutorien:
Was im einen nicht steht, steht im anderen. Was im einen unklar
bleibt, wird im anderen erklärt.
So, also ich habe jetzt alles wie im Tutorial angeschlossen, die lcd
routinen .h und .c erstellt und es wie folgt in mein Makefile
eingetragen:
CC= avr-gcc
CFLAGS= -Wall -mmcu=atmega16 -Os
LDFLAGS=-mmcu=atmega16
all: $(f)
$(f): $(f).o lcd-routines.o
$(f).hex: $(f)
avr-objcopy -j .text -j .data -O ihex $^ $@
brennen: $(f).hex
avrdude -u -e -c avrispmkII -P usb -p m16 -U flash:w:$^
clean:
$(RM) *.o $(f) *.hex
//////////////////////////////////7
Er kompiliert zwar ohne Probleme, jedoch wird nichts auf dem Bildschirm
angezeigt. Habe das LCD Beispiel 1 gebrannt.
Ich glaube das ich es irgendwie im Makefile falsch eingetragen habe, das
er als SRC die lcd-routine.c verwenden soll. Oder?
Tobias Neumann schrieb:> Er kompiliert zwar ohne Probleme, jedoch wird nichts auf dem Bildschirm> angezeigt. Habe das LCD Beispiel 1 gebrannt.
Das war auch nicht unbedingt zu Erwarten.
Dein LCD-Controller ist ein anderer als der im Tutorial verwendete.
Ähnlich aber doch anders. Da wird dir nichts anderes übrig bleiben als
die Datenblätter zu vergleichen und in der Initialisierung Anpassungen
an deinen Controller vorzunehmen.
also habe ich es im Makefile richtig eingetragen?
Mein Display verwendet ja auch den HD44780. Du meinst also das ich die
Initialisierung in der lcd-routine.h anpassen soll?
Tobias Neumann schrieb:> Mein Display verwendet ja auch den HD44780. Du meinst also das ich die> Initialisierung in der lcd-routine.h anpassen soll?
Datenblatt!!! Datenblatt!!! Datenblatt!!! Datenblatt!!!
Nochmal: Schau bitte ins Datenblatt und vergleiche selber, ob die
initialisierung im Code dazu passt.
Sorry wenn ich mich dumm anstelle.. bin nunmal ein totaler Newbie in
Sachen LCD. Ich habe ja das Datenblatt angehange.. kann mir einer sagen
wo diese Initialisierungsdaten stehen?.. Ich nehme an auf Seite 6 aber
ich werde daraus nicht so wirklich schlau :(
wenn ich das richtig lese, dann musst Du eigentlich gar nichts
initialisieren, das macht Dein Display nach dem Einschalten von alleine.
Allerdings muss man mit dem Senden von Daten warten bis das Busy flag
nicht mehr gesetzt ist.
Meine Vermutung, Du schickst zu schnell nach Power-On die ersten Daten.
Warte da einfach mal ne Sekunde und schau was passiert.
Gruß
Tom
Leider fehlt der Anhang, bzw. das Datenblatt noch immer.
Aus leidvoller (Zeitverschwendung) Erfahrung weiß ich,
daß es sehr sinnvoll ist sich an die Init-Routine
des Datenblatt zu halten, und nicht blind der vom
Displayhersteller zu vertrauen. Glücklicherweise sind
die Namen der Steuerleitungen bei (fast) allen die gleichen.
Achte auf die Position der Steuerbits im Datenbyte!!
Hier fand ich schon Unterschiede, aus der Erklärung
der Steuerbits habe ich dann Unterschiede (fast 100% kompatibel)
gefunden.
Mach die Wartezeiten ruhig etwas größer, so 50% stören für
den Beginn keinen, ich nehme nach der Init immer den Busy-
Flag-Test, ist zuverlässiger, und schneller.
Hallo Leute,
ich hab es leider immer noch nicht zum Laufen gebracht.. langsam
verzweifele ich. Ich weiß nicht wo ich aus dem Datenblatt sehe welche
Daten is wo in der lcd-routine.h reinschreiben muss. Ich denke mal das
ihr meint das ich folgnde Initialisierungsgeschichten anpassen muss wie
z.B:
// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY 0x02
// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME 0x02
// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY 0x04
#define LCD_ENTRY_DECREASE 0x00
#define LCD_ENTRY_INCREASE 0x02
#define LCD_ENTRY_NOSHIFT 0x00
#define LCD_ENTRY_SHIFT 0x01
Jedoch weiß ich nicht woher ich die richtigen Daten aus dem Datenblatt
entnehmen soll..
Tobias Neumann schrieb:> Hallo Leute,> ich hab es leider immer noch nicht zum Laufen gebracht.. langsam> verzweifele ich. Ich weiß nicht wo ich aus dem Datenblatt sehe welche> Daten is wo in der lcd-routine.h reinschreiben muss.
Nimm die LCD-Routinen als ANHALTSPUNKT
Du hast einen K_irgendwas Controller auf dem LCD und keinen Standard
HD44780.
Im Datenblatt auf Seite 6 ist die Initialisierungssequenz ausführlich
angegeben.
> Ich denke mal das> ihr meint das ich folgnde Initialisierungsgeschichten anpassen muss wie
Nein.
Was wir denken ist:
* du sollst dir am Tutorialcode grundsätzlich ansehen, wie LCD Routinen
aussehen können und dann sollst du hergehen und deine eigenen schreiben.
* du solltest C lernen
* du solltest mit etwas einfacherem anfangen als mit einem LCD
* du solltest dein LCD auf 8 Datenbits umverkabeln, dann dann (laut
Datenblatt Seite 6) brauchst du das LCD gar nicht explizit
initialisieren, weil der Controller auf dem LCD schon eine brauchbare
Basisinitialisierung macht
* du sollst die relevanten Teile im Datenblatt aufmerksam lesen,
verstehen, ausprobieren und umsetzen und dich nicht darauf verlassen,
dass dich hier im Forum irgendjemand da durchsprechen wird. Letzteres
wird höchst wahrscheinlich schief gehen, weil hier niemand deine
Hardware vor sich liegen hat und wir daher 'blind' arbeiten müssen.
* du sollst dein Programm so umbauen, dass du die LCD Initialisierung zb
mit einem Tasterdruck um jeweils einen Schritt weiter laufen lassen
kannst. Dies deshalb, weil du dann mit einem Voltmeter die Pegel an den
einzelnen Pins ansehen und mit der Vorgabe im Datenblatt vergleichen
kannst.
Edit: Beim Hochscrollen gesehen - du hast ja alle 8 Datenpins
angeschlossen. Also vergiss die Sache mit dem Umverkabeln. AVcc vom
Prozessor hast du beschaltet?
Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht. Es
ist nicht so das ich gerade mit Mikrokontrollern angefangen habe.. und
mit C arbeite ich auch schon seit 2 Jahren.
Ich habe jetzt wieder alle 8 Datenpins angeschlossen und versuche jetzt
mit hilfe von Tutorial und Datenblatt mein eigenes kleines
Beispielprogramm zu schreiben wo einfach nur einen Char auf dem
Bildschirm ausgibt und es danach wieder cleared. Mal schauen ob ich das
hin kriegen ;)
Also ich habe nun ein Beispielprogramm geschrieben was leider nicth
funktioniert. Ich habe auch eine lcd-routine.h geschrieben. Ich habe
dabei alles berücksichtigt was auch in der lcd-routine.h vom Tutorial
steht, außer diesen Teil:
#define LCD_SOFT_RESET 0x30
//Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
#define LCD_SET_CGADR 0x40
#define LCD_GC_CHAR0 0
#define LCD_GC_CHAR1 1
#define LCD_GC_CHAR2 2
#define LCD_GC_CHAR3 3
#define LCD_GC_CHAR4 4
#define LCD_GC_CHAR5 5
#define LCD_GC_CHAR6 6
#define LCD_GC_CHAR7 7
// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
#define LCD_SET_DDADR 0x80
Diesen Teil kann ich aus meinem Datenblatt nicht wirklich entnehmen..
hat einer ne Idee was ich da laut Datenblatt angeben muss?
Mein Programm sollte den String "Hello World!" über die funktion
lcd_string() ausgeben. Aber er er leuchtet nur jede einzelne Zelle des
Displays mit verschiedenen grau stufen auf.. also es sind keine Zeichen
auf dem Display zu sehen aber irgendwas passiert schonmal.. wenigstens
was!
Tobias Neumann schrieb:> Hm, ich versteh nicht ganz wie mir das bei meinem Problem helfen soll..> :)
Weil das ein ziemlich narrensicherer Code ist.
Er macht nicht ähnliche Sachen an 6 verschiedenen Stellen, sondern ist
streng modular.
Außerdem erlaubt er beliebige Pinzuordnung.
Je nach LCD können kleinere Änderungen im Init oder in der
Positionierung nötig sein, aber mehr nicht.
Peter
Tobias Neumann schrieb:> Ich wollte mal meine Eigene lcd init posten und euch fragen ob ich das> denn so richtig mache, weil mein Programm funktioniert immer noch nicht> und ich hab immernoch nur die zwei Balken auf dem Display:
Was soviel heißt wie:
Deine Initialisierung stimmt nicht.
> Programmtechnisch habe ich das so geloest:>> ------------------------------------------------------------------>> void lcd_init( void )> {> DATA_DDR = 0xFF;> SET_DDR = 0xE0;>> //-----Enable Display-------//> _delay_ms(5000);> lcd_enable();> _delay_ms(200);>
Der Enable Pin heißt nicht 'Enable', weil er das LCD einschaltet.
Er ist das Signal an das LCD, dass die restlichen Leitungen jetzt einen
stabilen Zustand angenommen haben und daher vom LCD als gültig anzusehen
sind. Wenn man will, kann man das so sagen: 'Jetzt gilts. Das was jetzt
an den Leitungen anliegt, sind gültige Werte'
> //--------1--Fset------------------//> DATA_PORT |= (1<<PA4);> DATA_PORT |= (1<<PA5);> _delay_ms(500);>> DATA_PORT &= ~(1<<PA4);> DATA_PORT &= ~(1<<PA5);> _delay_ms(500);
Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den
ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4
und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein
Programm eine halbe Sekunde wartet?
Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem
LCD mitzuteilen: Jetzt gilts!
> oder> daran das ich vielleicht mit 8 Datenpins arbeite und die> Funktions lcd_data() angepasst werden muss. Ich hoffe ihr könnt mir> dabei helfen.
Deine Funktion lcd_data + lcd_out ist ein einziger Schmarrn. Ein
Mischmasch aus 4Bit und 8 Bit Anteuerung, wobei weder das eine noch das
andere sauber durchgezogen ist.
Tu dir selbst einen Gefallen und studiere erst mal anderen Code! Aber
wirklich studieren und nicht einfach nur drüberschauen! Anweisung für
Anweisung durchgehen. Abklären welchen Einfluss das auf die Pins hat,
mit dem Datenblatt abklären was da passiert und warum ausgerechnet jetzt
dieser Pin auf den Zustand gebracht wird, der im Programm steht.
> Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht.> Es ist nicht so das ich gerade mit Mikrokontrollern angefangen habe..> und mit C arbeite ich auch schon seit 2 Jahren.
Wenn ich deinen Code so ansehe: Ich mag es kaum glauben.
> VO -> nicht angeschlossen
Da bist du recht lapidar drüber hinweggegangen.
So lange VO (VEE) nicht richtig bedient wird,
normalerweise also per Poti die passende Spannung zwischen 0V und 5V
gefunden wird,
bei manchen Displays sogar eine negative Spannung (bei deinem nicht)
kannst du initialisieren wie du willst und nichts ist zu sehen.
Ganz abgesehen von den Problemen die die Anderen im Programm gefunden
haben.
Karl heinz Buchegger schrieb:> Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den> ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4> und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein> Programm eine halbe Sekunde wartet?>> Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem> LCD mitzuteilen: Jetzt gilts!
Es könnte sein, dass ich mich da in deinem Code verlesen habe.
Dein Mischmasch aus PA4 PA5 DATA_PORT SET_PORT und LCD_EN sucht aber
auch seinesgleichen und ist hauptsächlich Eines: maximale Verwirrung!
Wobei aus dem Code immer noch nicht hervor geht:
Ist PA4 PA5 jetzt eine Steuerleitung oder sind das Datenleitungen? In
deinem lcd_out kann man das auch nicht ablesen. Die gibt zwar laut
Kommentar nur einen Nibble aus, verändert allerdings alle 8 Leitungen
(und das auch nur in Richtung 0->1).
Hallo,
habe die Initialisierung von diesem Beitrag hier und an meine
Pinbelegung angepasst: Beitrag "Hilfe bei KS0076B"MaWin schrieb:>> VO -> nicht angeschlossen>>> Da bist du recht lapidar drüber hinweggegangen.>> So lange VO (VEE) nicht richtig bedient wird,>> normalerweise also per Poti die passende Spannung zwischen 0V und 5V> gefunden wird,> bei manchen Displays sogar eine negative Spannung (bei deinem nicht)> kannst du initialisieren wie du willst und nichts ist zu sehen.>> Ganz abgesehen von den Problemen die die Anderen im Programm gefunden> haben.
V0 hab ich über einen Poti an 5V angeschlossen. Ich sehe zwei Balken,
also müsste der Kontrast soin ordnung sein.
Karl heinz Buchegger schrieb:> Der Enable Pin heißt nicht 'Enable', weil er das LCD einschaltet.> Er ist das Signal an das LCD, dass die restlichen Leitungen jetzt einen> stabilen Zustand angenommen haben und daher vom LCD als gültig anzusehen> sind. Wenn man will, kann man das so sagen: 'Jetzt gilts. Das was jetzt> an den Leitungen anliegt, sind gültige Werte'
Das mit lcd_enable habe ich jetzt verstanden, habe es jetzt aus der
initialisierung genommen.
Karl heinz Buchegger schrieb:> Warum denkst du, verweisen wir dich immer auf anderen Code? Damit du den> ignorierst? Woher soll denn dein LCD wissen, dass genau jetzt die an PA4> und PA5 anliegende 1 schon der endgültige Zustand ist? Weil dein> Programm eine halbe Sekunde wartet?>> Du musst schon mit den Steuer-Pins wackeln (konkret dem Enable) um dem> LCD mitzuteilen: Jetzt gilts!
Ich versteh nicht ganz was du damit meinst.. soll ich jetzt nach jeder
Fset anweisung noch ein lcd_enable machen??
Karl heinz Buchegger schrieb:> Deine Funktion lcd_data + lcd_out ist ein einziger Schmarrn. Ein> Mischmasch aus 4Bit und 8 Bit Anteuerung, wobei weder das eine noch das> andere sauber durchgezogen ist.
Ja, ich bin in diesen Bitverknüpfungsgeschichten noch sehr unsicher..
könntest du mir denn eine funktionierende lcd_data+lcd_out für eine 8
Bit Datenübertragung schreiben?
Karl heinz Buchegger schrieb:>> Ja ich habe schon viele Sachen mit meinem Mikrocontroller gemacht.>> Es ist nicht so das ich gerade mit Mikrokontrollern angefangen habe..>> und mit C arbeite ich auch schon seit 2 Jahren.>> Wenn ich deinen Code so ansehe: Ich mag es kaum glauben.
Ja ich habe davor mit den ganzen Interrupts gearbeitet und LEDs
geschaltet, ein Zaehlrohr angeschlossen und solche Dinge. Ich arbeite
jetzt vielleicht seit ung. 8 Wochen mit dem ATmega8. Mit C arbeite ich
seit knapp 2 Jahren. Wobei ich erst vor kurzem mit diesen Bitoperationen
angefangen habe... entschuldige bitte.
Karl heinz Buchegger schrieb:> Ist PA4 PA5 jetzt eine Steuerleitung oder sind das Datenleitungen?
PA0 - PA 7 sind meine Datenleitungen. Diese habe ich in meinem init
direkt reingeschrieben.
RS = PD5
R/W = PD6
E = PD7
// LCD RS <--> PORTD Bit PD5 (RS: 0=Data, 1=Command)
#define LCD_RS PD5
// LCD EN <--> PORTD Bit PD7 (EN: 1-Impuls für Daten)
#define LCD_EN PD7
Sorry für meine Verwirrende schreibweise
Also Leute,
ich habe mein Programm jetzt nochmal komplett überarbeitet und den
Quelltext nun leserlich gestalltet (hoffentlich :)). Ich habe im Anhang
mein .c file angehängt. Ich habe immernoch ein Initialisierungsproblem,
da die schwarzen Balken auf meinem Display nicht verschwinen. Irgendwas
mach ich noch falsch. Wäre nett wenn einer mal meine Initialisiesung mit
dem Datenblatt welches ich auch nochmal angehangen habe durchgeht und
mir sagt was ich falsch mache.
Danke, Tobias.
Ich seh immer noch keine Enable Pulse, die dem LCD mitteilen: Jetzt
gilts.
OK. Analogie
Du und dein Kumpel Herbert habt eine ganz besondere Form der
Kommunikation:
Vor jedem ist ein Schaltbrett mit Leuchten und darunter jeweils Schalter
die entweder ein oder aus sein können.
Die Schalter sind jeweils mit den Leuchten der Gegenstelle verbunden, so
dass wenn du bei dir den Schalter 0 auf 'ein' stellst, beim Herbert die
Lampe 0 aufleichtet. Und natürlich umgekehrt, betätigt Herbert seinen
Schalter, so leuchtet bei dir eine Lampe auf.
Ihr macht euch beide einen Code aus. Wenn die und die Lampenkombination
aufleuchtet, dann bedeutet das irgendwas. Mit anderen Kombinationen
natürlich auch, die eben dann was anderes bedeuten.
Also legt ihr los.
Du starrst auf deine Lampen.
Die leuchten nacheinander auf, gehen wieder aus, leuchten wieder etc. Du
weisst nie, ob eine bestimmte Leuchtkombination jetzt gültig ist oder
nicht, denn natürlich vertut sich Herbert auch mal ab und zu. Er
schaltet eine Lampe ein, die eigentlich aus sein sollte und umgekehrt.
Herbert bemerkt das auch und schaltet schnell die Lampe wieder aus. mit
seinen Wurstfingern kann er nicht alle Lampenschalter gleichzeitig
betätigen, ab und zu muss er ins Codebuch schauen um die angestrebte
Lampenstellung abzulesen. Kurz und gut: Woher sollst du denn als
Beobachter der Lampen wissen, wann Herbert jetzt seine Schalter
endgültig in der richtigen Stellung hat und das was bei dir aufleuchtet
jetzt tatsächlich eine Nachricht von ihm ist?
Eben. Du kannst es nicht wissen.
Und daher macht ihr beide einen Zusatz:
Ihr verlegt noch einen zusätzlichen Schalter auf jeder Seite, der in
einer elektrischen Glocke auf der Gegenseite mündet. Jedesmal, wenn
einer seine Schalter so hat, wie er das haben möchte, betätigt er
zusätzlich den Schalter der beim anderen die Glocke läuten lässt.
Und plötzlich geht alles wie geschmiert.
Du siehst wie auf deinem Brett Lampen an und ausgehen und ... 'Bimmel'
Die jetzt anliegende Lampenstellung ist die Nachricht
Weiter: die Lampen machen wieder einen Tanz, gehen an und aus, einmal
kannst du sogar erkennen, wie sich Herbert vertan hat und eine Lampe
zuerst ein und dann wieder ausgeschaltet hat. Aber das macht nichts.
Solange Herbert nicht bimmelt, kann er mit den Lampen machen was immer
er will.
'Bimmel' - Herbert hat seine Schalter kontrollier, hat sie für richtig
befunden und hat gebimmelt. Damit gilt die zum Zeitpunkt des Bimmelns
anliegende Lampenkonfiguration für dich. Alles dazwischenliegende ist
egal. Nur die Lampen die zum Zeitpunkt des Bimmelns leuchten (oder nicht
leuchten) gelten. Mit der Betonung auf 'zum Zeitpunkt des Bimmelns'.
Das ist die grundlegende Idee, die hinter dem Enable Pin des LCD steckt.
Du kannst an den Datenpins umstellen soviel du willst, du kannst am R/W
am Command/Data Pin rumstellen soviel du willst. Ist alles egal. Erst
wenn der Puls am Enable kommt, dann gilt die zu diesem Zeitpunkt
anstehende Einstellung und das LCD übernimmt die dann anliegende
Pinkonfiguration und bearbeitet sie.
Ist doch nicht so schwer zu verstehen.
der TE sollte sich langsam darüber gedanken machen ob er programmieren
WILL
das ist jetzt quasi eine grundsatzfrage ...
ohne weitere C kenntnisse und wie so ein µC sowie solche signale
funktionieren kommt man hier nicht weiter
bzw ist es ein absoluter frust sich unwissend durch Code zu wühlen
ohne nur ansatzweise zu verstehen wie es funzt
wenn er will .. dann muss er lernen ...
wenn er nicht will ... kann er sich maximal projekte nachbauen die
seinem anspruch genügen
alles andere führt nur dazu das hier elend lange threads entstehen wo zu
90% geflamed wird ..
Ich bewundere ja Kar Heinz für seine Geduld mit dem TE, aber ich stimme
dem roflkartoffel zu, wir können nicht jemandem, dem so elemtare
Grundkenntnisse fehlen komplett Schritt für Schritt vorkauen wie er sein
Programm zu schreiben hat.
Meine Meinung, Tom
roflkartoffel schrieb:> ohne weitere C kenntnisse und wie so ein µC sowie solche signale> funktionieren kommt man hier nicht weiter> bzw ist es ein absoluter frust sich unwissend durch Code zu wühlen> ohne nur ansatzweise zu verstehen wie es funzt
Wobei man auch sagen muss, das 90% dieser Techniken in Wirklichkeit
wahnsinnig simpel sind. Ich kann aber nicht ewig Beispiele konstruieren,
die eine bestimmte Thematik losgelöst von Elektronik, Computern und
Programmen beleuchten, um zu zeigen warum etwas so gemacht wird, so wie
hier mit dem Enable Signal. Ob das jetzt Enable, Strobe (beim Centronics
Druckerinterface), SCLK bei der Ansteuerung von Schieberegistern ...
oder eben Herberts Bimmeln ist, es ist immer dieselbe Grundidee. Und es
sind diese Grundideen, die man (neben natürlich technischem Handwerk,
sprich Programmieren) verstehen muss, welches Problem sonst entsteht und
wie die Idee genau dieses Problem eliminiert.
Irgendwann muss er soweit sein, solche Ideen aus dem Datenblatt
herauszulesen, bzw. wenn schon fremder Code vorhanden ist, diese Idee im
Code sehen. In allen Codevorlagen ist die Reihenfolge: Bits an den
Datenbports, Bits an den Steuerleitungen und dann "Enable auf 1; Enable
auf 0". Da muss ich mich doch irgendwann, wenn ich das im Code lese,
fragen: Warum ist denn das so? Was steckt da dahinter?
> wenn er will .. dann muss er lernen ...> wenn er nicht will ... kann er sich maximal projekte nachbauen die> seinem anspruch genügen
Jup.
Der Unterschied zwischen 'Malen nach Zahlen' und 'Rausgehen in die Natur
und das malen was man sieht'.
Edit: Timer sind auch so ein Kapitel.
Wahnsinnig simpel und trotzdem für Neueinsteiger so schwer zu verstehen.
Ich weiß nicht warum, aber im relen Leben lösen Menschen genau dieselben
Probleme ohne groß darüber nachzudenken. Nur wenn es um Computer und
Programme geht, ist genau derselbe Sachverhalt plötzlich unendlich
schwierig zu lösen.
Völlig richtig! Daher kommt es auch überhaupt nicht darauf an, ob man
eine bestimmte Programmiersprache kann oder nicht, die Grundprinzipien
sind davon unabhängig.
Wenn er sich durch Beispielcode wühlt und dabei an einer Stelle nicht
versteht warum dort etwas bestimmtes gemacht wird, dann kann er ja genau
danach Fragen, aber dann hat er zumindest den Rest schon mal verstanden.
Tom
Ganz ruhig bleiben.. Diejenigen die meinen mich hier beleidigen zu
müssen sollen lieber mal garnichts schreiben. Ich versuche mein bestes
und habe nunmal gerade erst mit LCD Displays angefangen und habe mich in
der hinsicht vielleicht etwas schwer getan.
An diejenigen die mich unterstützen, wie z.B Karl Heinz:
Ich habe nun die Initialisierung ENDLICH hinbekommen.. nachdem du mir so
anschaulich beschrieben hast wozu das ENABLE wirklich dient :). Danke
schonmal dafür!
Meine Initialisierung sieht nun wie folgt aus:
void out_stat_reg (unsigned char command)
{
PORTA=0;
PORTD &= ~(1<<PD6);
_delay_ms(5);
PORTD |= (1<<PD7); // Enable auf 1 setzen
PORTA=command;
PORTD &= ~(1<<PD7); // Enable auf 0 setzen
_delay_ms(70);
}
// Initialisierung:
void lcd_init( void )
{
//Pins auf schreiben schalten (PA0-PA7) (PD5-PD7)
DDRA = 0xFF;
DDRD = 0xE0;
//Pins alle low setzen
PORTA = 0;
PORTD = 0;
//Wait untill VDD rises to 4,5V
_delay_ms(2000);
//Function Set 1
PORTD |= (1<<PD7); // Enable auf 1 setzen
PORTA = 0x30; //Set PA4 und PA5 high
PORTD &= ~(1<<PD7); // Enable auf 0 setzen
_delay_ms(2000);
//Function Set 2
PORTD |= (1<<PD7); // Enable auf 1 setzen
PORTA = 0x30; //Set PA4 und PA5 high
PORTD &= ~(1<<PD7); // Enable auf 0 setzen
_delay_ms(2000);
//Function Set 3
PORTD |= (1<<PD7); // Enable auf 1 setzen
PORTA = 0x30; //Set PA4 und PA5 high
PORTD &= ~(1<<PD7); // Enable auf 0 setzen
_delay_ms(2000);
out_stat_reg(0x3c); //set Display
lines
out_stat_reg(0x08); //Display off
out_stat_reg(0x01); //Display clear
out_stat_reg(0x06); //cursor
increase
out_stat_reg(0x0c); //Display on
}
Ich hoffe das ist nun verständlicher und sieht mal n bisschen besser aus
als das was ich vorher fabriziert habe ;)
Also es erscheinen nun die Zeichen "Lo<-" anstatt "Hello World!" auf dem
Display. Aber wenigstens hat die Initialisierung schonmal funktioniert.
Jetzt muss ich nurnoch rausfinden warum er nicht meinen gewünschten
String ausgibt. Ich probier mal ein paar Dinge aus, wenn jemand n
Vorschlag hat woran es liegen könnte kann er es ruhig hier posten.
Danke erstmal an die jenigen die so Geduldig mit mir waren.
Hallo,
also ich kann jetzt einen beliebigen char an das Display übergeben..
weiß aber nicht wie ich den Curser bewege. Wie kann ich dem Display denn
sagen, das er, nachdem er einen char geschickt bekommen hat eine
curserposition nach rechts rücken soll?
Gruß, Tobias.
Schaust du in dein Datenblatt, auf Seite 5 sind alle
Konfigurationskommandos zusammengestellt.
Das LCD verändert die Cursor Position sowieso von sich aus nach jedem
Zeichen. Mit der Konfiguration 'ENTRY MODE SET' kannst du dann noch
festlegen, ob der Cursor nach Ausgabe eines Zeichens nach rechts oder
nach links wandern soll.
Bsp
Aus dem Datenblatt
RS R/W 7 6 5 4 3 2 1 0
ENTRY MODE SET L L L L L L L H I/D SH
I/D H = increase
L = decrease
SH H = Display is shifted
L = Display is not shifted
Du willst: Cursor soll automatisch nach rechts ( = increase)
Displayanzeige wird nicht verschoben
also I/D muss H (also 1) sein und sH muss L (also 0) sein.
Dein Commandobyte ist also
LLLLLHHL
oder in gebräuchlicher 0/1 Schreibweise
0b00000110
in Hex soviel wie 0x06
Dieses Kommando schickst du zum LCD und dann macht es das Gewünschte.
Edit: Seh gerade, dass das in deiner Init Sequenz sowieso enthalten ist.
Zeig mal dein Programm. Wahrscheinlich wimmelt es da wieder mal von
Cursor Home bzw. LCD Clear Aufrufen.
Ok.
Ich habe nur ein ganz einfaches Programm erstellt wo direkt in der main
den char sendet. Wenn ich genau weiß wie das richtig funktioniert will
ich dann meine eigene putchar funktion erstellen.
Meine init() kennst du ja.
Meine main:
int main(void)
{
lcd_init();
PORTD |= (1<<PD5); //RS auf 1
PORTA = 0x54; //send char 'T'
lcd_enable(); //Jetzt gilts
while(1)
{
}
return 0;
}
Naja, ich frage mich halt grade wie das genau Funktioniert.
Ich habe jetzt versucht so zwei char nebeneinander zu senden:
int main(void)
{
lcd_init();
PORTD |= (1<<PD5);
PORTA = 0x54;
lcd_enable();
PORTD |= (1<<PD5);
PORTA = 0x4F;
lcd_enable();
while(1)
{
}
return 0;
}
UNd führ dir endlich für PORTA und PDirgendwas und was du sonst noch so
an Konstnaten hast, vernünfitge #define ein!
1
#define LCD_DATA_PORT PORTA
2
#define LCD_CTRL_PORT PORTD
3
4
#define LCD_RW_PIN PD6
5
#define LCD_RS_PIN PD5
6
#define LCD_E_PIN PD7
7
8
voidputchar(charc)
9
{
10
LCD_CTRL_PORT|=(1<<LCD_RS_PIN);
11
LCD_CTRL_PORT&=~(1<<LCD_RW_PIN);
12
13
LCD_DATA_PORT=c;
14
15
LCD_CTRL_PORT|=(1<<LCD_E_PIN);
16
_delay_ms(1);
17
LCD_CTRL_PORT&=~(1<<LCD_E_PIN);
18
}
19
20
voidout_stat_reg(unsignedcharcommand)
21
{
22
LCD_DATA_PORT=0;
23
LCD_CTRL_PORT&=~(1<<LCD_RW_PIN);
24
25
_delay_ms(5);
26
LCD_CTRL_PORT|=(1<<LCD_E_PIN);
27
LCD_DATA_PORT=command;
28
LCD_CTRL_PORT&=~(1<<LCD_E_PIN);
29
_delay_ms(70);
30
}
31
32
33
etc.....
erstens wird der Code dadurch sehr viel besser verständlich, als wie
wenn man ständig im Hinterkopf behalten muss, welcher Pin am Port D dann
jetzt welche Leitung ist und zweites hast du dann die Pinbelegung an
einer Stelle beisammen, was bei Änderungen ja höchst vorteilhaft sein
soll.
Tobias Neumann schrieb:> Naja, ich frage mich halt grade wie das genau Funktioniert.
Du gibst das Byte einfach auf dem Port aus. Allerdings muss die RS
Leitung dazu High sein.
(Und natürlich, wie immer, hinten nach ein Enable Puls)
Siehe Datenblatt, Seite 5, in der Tabelle fast ganz unten, das
'Kommando' Write Data
Tobias Neumann schrieb:> Er zeigt mir aber nur ein 'H' an, wenn ich es so mache :/
Wie sieht deine lcd_enable aus?
Hast du dir inzwischen ein paar #define gemacht, damit man nicht ständig
mit PD5, PD6 und Konsorten durcheinanderkommt?
Hast du nach dem Enable Puls ein bischen gewartet? Laut Tabelle benötigt
die Ausgabe auch Zeit (42µs)
....
JAAAAAAAAAAAAAAAAAAAAA!
Ich habs endlich geschafft!!!! DANKE Karl Heinz ich LIEBE DICH :D
Das Problem war das ich mal wieder zu "copy&paste" geil war und ich
deine defines rauskopiert habe, wobei du RS = PD6 und RW = PD5 definiert
hattest. Diese sind aber genau umgedreht.. das hat mich grad zur
verzweiflung gebrahct.. aber jetzt gehts! DANKE DANKE DANKE
Ich hab mein Programm mal in den Anhang gemacht, falls du es dir nochmal
anschauen willst.
Gruß, Tobias.
Tobias Neumann schrieb:> Ich hab mein Programm mal in den Anhang gemacht, falls du es dir nochmal> anschauen willst.
Ich halt mich da jetzt raus.
Nur eines noch:
Du solltest anfangen auf Nomenklatur zu achten.
Die eine Funktion heisst lcd_init, die andere out_stat_reg, dann wieder
eine lcd_enable und die letzte putchar
Was haben all diese Funktionsnamen gemeinsam?
Richtig. Bis auf lcd_init und lcd_enable, die die gemeinsame 'Vorsilbe'
lcd benutzen: Gar nichts
Alle diese Funktionen gehören aber zum selben Code-'Modul'. Nämlich der
Ansteuerung des LCD!
Das sollte sich dann schon im Funktionsnamen niederschlagen.
Den irgenwann hast du dann 25 vrschiedene Zeichen-Sende Routinen und
weißt nicht mehr welche jetzt für UART, welche für SPI, TWI, LCD etc.
zuständig ist.
Und den Wildwuchs mit ENABLE solltest du auch beseitigen. Entweder von
überall her wird lcd_enable aufgerufen, wenn man einen Enable Puls
braucht, oder die Funktion fällt komplett weg. Aber nicht so wie jetzt.