Initialisierung alphanumerisches LCD (HD44780)

uwe_n

Neues Mitglied
26. Apr. 2007
1
0
0
Sprachen
Hallo,

ich habe Schwierigkeiten mit der Initialisierung eines alphanumerischen LCD mit HD44780 Controller. Hat da jemand mal einen fertigen Code, möglichst in Assembler (mit C komme ich aber auch zurecht).

Schon mal vielen Dank!

Uwe
 
Hallo,

es muß nicht unbedingt an der Initialisierung des LCD-Controllers liegen. Wichtig ist das Protokoll und der richtige Anschluß des LCD an den Mikrocontroller.

Könntest du vielleicht ein bisschen von deiner Software posten, vielleicht hast du ja nur einen kleinen Fehler im Code.

Für die Initialisierung des LCD ist folgendes wichtig:
  • Anzahl der Zeilen des LCD
  • 4Bit- oder 8Bit-Modus
Grüße,
Dirk
 
hallo uwe_n,

bei der initialisierung muss auch die execute time umbedingt eingehalten werden. Zum Beispiel: nach dem einschalten des Displays braucht der Controller 15ms um einen internen reset zu starten, oder CLEAR DISPLAY braucht ca. 2ms. Genaue Daten stehen aber müssen beim Display dabei sein.

Gruß

max
 
Hallo Uwe,

fallst Du eine Lösung über Basic mit dem BASCOM-AVR Basic-Compiler suchst dann kann Dir veilleicht auch geholfen werden.

Lass es uns einfach wissen.

Grüße,
Markus
 
Ich beschäftige mich auch gerade mit der Thematic aber ich bekomme es nicht hin. Anbei einmal der Code den ich bisher benutze, ja ich weiß der ist sehr umständlich aber ich beschäftige mich das erste mal seid Jahrzehnten wieder damit. Hoffe das mir wer weiterhelfen kann.

.include "m128def.inc"
.macro delay15ms
LDI ZH, HIGH (3600)
LDI ZL, LOW (65535)
zaehlschleife1:
SBIW ZL,1
BRNE zaehlschleife1
.endmacro
.macro delay4100
LDI ZH, HIGH (1000)
LDI ZL, LOW (65535)
zaehlschleife1:
SBIW ZL,1
BRNE zaehlschleife1
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
.endmacro
.macro delay120
LDI ZL, LOW (40)
zaehlschleife1:
SBIW ZL,1
BRNE zaehlschleife1
.endmacro
clr r16 ;Inhalt Register R16 löschen
ldi r16,0b11111111 ;Wert FF in Register laden
out ddra,r16 ;Datenrichtung PortA auf Out setzen
out ddrc,r16 ;
ldi r16,0b00001111 ;Wert 30 in Register laden
ldi r17,0b00000000 ;Wert 0 in Register laden
out PortA,r16;
out PortC,r17;
delay15ms ;
delay120
ldi r16,0b00111000 ;
out PortA,r16;
delay4100 ;
delay120
ldi r16,0b00111000 ;
out PortA,r16;
delay120 ;
delay120
ldi r16,0b00111000 ;
out PortA,r16;
delay120 ;
delay120
ldi r16,0b00111000 ;
out PortA,r16;
delay120 ;
delay120
ldi r16,0b00001111 ;
out PortA,r16;
ldi r16,0b00000001
out PortA,r16
out PortC,r16

Also PortA ist der Datenbus in 8 Bit und PortC-0 ist RS, PortC-1R/W, PortC-2 ist Enable 2 und PortC-3 ist Enable 1. Es handelt sich dabei um das Display 404B von www.Displaytech.com mit 4x40.
 
Hallo,
bei vierzeiligen Displays muß auch die gesamte Suite durchlaufen werden, die fehlt in Deinem Code. Auch muß oft jeder Zeilen-Controller gesondert initialisiert werden. (glaube Hex C2- lies mal in der Doku nach.) Die Software hernach kann auch jeden einzelnen Zeilencontroller gesondert noch ansprechen. Bin mal dabei, Dir den Link rauszusuchen- Momang..
Sinnigerweise sind die Vierzeilen-LCDs so organisiert:
1/3
2/4
die Darstellung ist nicht konsekutiv, will heißen, der Text wird nicht fließend zeilenweise "umgebrochen", sondern wechselt oft nach obigem Schema.
Das müßtest Du aber anhand der Adressenbezeichnung rausfinden können.
Normalerweise - 16 Stellen- 2 Zeilen - sieht der Adresscode so aus:
00 Pos 1 oben (Eingabe Hex 80, da ja das Steuerbit 7 noch reinkommt!)
40 Pos 1 unten (Eingabe Hex C0 ...)


H28
H28
H01
H02
H06
H0E (auch H0F 'Blink')
===> Daten

reicht nicht. Das ist nur zweizeilig Vierbit-Modus.

Gruß von Oskar01
 
also es ist dem Display zur Zeit egal ob ich den Atmega drann habe oder nicht. Es stellt die Zeile 1 und 3 als schwarzen Balken dar. Daher denke ich das weder der erste, geschweige den der zweite Controller initialisiert wurde.

Das sagt das Datenblatt dazu

u Initializing by Instruction
Power On
|
Wait for more than 15ms after VDD rises to 4.5V
|
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 * * * *
BF cannot be checked before this instruction.
Function Set
|
Wait for more than 4.1ms
|
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 * * * *
BF cannot be checked before this instruction.
Function Set
|
Wait for more than 100ms
|
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 * * * *
BF cannot be checked before this instruction.
Function Set
|
|
|
|
|
BF can be checked after following
instruction.
When BF is not checked, the waiting time
between instructions is longer than execution
instruction time.
|
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 N F * *
Function Set (Specify the number of display
lines and character font.) The number of
display lines and character font cannot be
changed afterwards.
0 0 0 0 0 0 1 0 0 0 Display Off
0 0 0 0 0 0 0 0 0 1 Display Clear
0 0 0 0 0 0 0 1 I/D
S
Entry Mode Set
|
â
Initialization ends
 
Sieht gut aus...

Hallo @y...,
sieht gut aus, also Kontrastspannung zeigt schwache Balken auf Zeilen 1 und 3 (siehe Vermutung oben).
Zum Test würde ich mich erst mal begnügen, diese beiden Zeilen "zum Leben" zu erwecken.
Der Code ist eins zu eins der allenthalben gebräuchlichste, also:
Hex 30
Hex 30
Hex 30
Hex 38
Hex 38 (Redundanz)
Hex 08
Hex 01
Hex 02 (Redundanz)
Hex 06
Hex 0E (oder 0F bei Blinken)

Dabei ist jetzt von entscheidender Bedeutung, daß die Wartezeiten zwischen den einzelnen Kommandos groß genug sind, da die Displays ohne Busyflag-Abfrage grottenschlecht langsam arbeiten.
Laß die Busyflag-Abfrage erst mal weg durch Legen des R/WQuer-Pins nach Masse zunächst auf Dauer-Low. Sonst gibt es unter Umständen Datenkollision, wenn
die Software den ATMega -Port gleichzeitig wie den Display-Port auf Ausgang schaltet, das könnte beide unter Umständen zerstören.
Ferner wird zunächst noch RS- und Enable-Impulserzeugung mit Argusaugen unter die Lupe genommen werden müssen. Auch die Zeiten für das stabile Anlegen des Kommandos bzw. der Daten ist noch wichtig. Die Displays brauchen auch hier oft unverhältnismäßig viel Zeit zur Verarbeitung, insbesondere der "Display Clear/Cursor Home". Lieber noch ein paar Zeitschleifen mit unterschiedlichen Verzögerungszeiten vorab programmieren oder NOPs reinsetzen, die sukzessive ja später reduziert werden könnten.
Dabei gibt es noch folgendes zu beachten, am Anfang besser mehfach kleinere Zeitschleifen hintereinandersetzen, da die ATMegas oft größere nicht mögen, bzw. es bei Interrupts hernach je nach Konfiguration des "Hauptprogramms" massive Konflikte geben könnte.

Also, Schema von Verzögerungs- bzw. Zeitschleifen:
Load
count
Verzweigung
Sprung in Count
Ret

oder:

load bereits im Programm oben
rcall
zu Verzoegerung
im Label Verzoegerung
dann Count
Compare
Branch
Return
und das Ganze ca. 10 bis 20-mal hintereinander. (Hinterher wird es etwas eleganter ok, wir sind ja am Testen. Beispiel , wie man Zeitschleifen etwas genauer berechnet, ist ja im Proggi drin. Man kann auch sagen: Zeit zur Befehlsabarbeitung mal Ladewert mal Anzahl der Befehle in der Schleife, über den Daumen gepeilt, also dreimal Ladewert mal Prozessortakt, bei 4 MHz also 250 Nanosekunden pro Takt. OK, der Branchbefehl ist mal einen Takt-Zyklus, mal zwei lang. Dann wird die Schleife ja am Anfang noch mit den Load-Befehlen, und wers genau haben möchte, noch mit den aufrufenden und Return-Befehlen berechnet. Und zu guter letzt muß noch ein Ladewert abgezogen werden, da bei Branchbedingung die Schleife nicht voll durchgerattert wird.)
Dabei ist es eigentlich egal, welcher Branch-Befehl genommen wird.
Ich arbeite gerne mit dem Brlt, der das Signier-Flag ("Negative"-Zahlen-Erkennung ) zusammen mit dem cpi Befehl benutzt.
OK, die Zeitschleifen haben es in sich, daher - Entschuldigung - etwas ausführlicher. Oft sind auch die Label falsch gesetzt, so daß der MC sich da gerne "aufhängt", springt immer wieder in den "Load" rein, so kann er immer wieder von vorne anfangen. Habe die "Loads" bewußt mit in die Schleife reingenommen, etwas Zeit wird dabei auch noch rausgeschunden. Wichtig dabei ist, daß bei meinen Beispielen für die Ladeanweisungen jeweils extra Register reserviert werden müssen.
Man kann natürlich auch mit push und pop "temp" sichern und so wiederverwenden, traue aber dem Braten nicht.
(Der Stack wird anderweitig schon gebraucht, wohl.)

Dann zum allerersten Test:
direkt hinter der Initialisierungsroutine:
RS-Impuls auf highEnable auf high
ldi temp, 0x41
out Ausgabeport, temp
nop ; vielleicht 10 Stück
Enable auf low
nop ; vielleicht 10 Stück
RS kann high bleiben oder auch nicht
Jetzt müßte zu sehen sein:

A_
Buchstabe "A" erscheint ganz links oben in erster Zeile, gleichzeitig rutscht Cursor eine Stelle weiter nach rechts (laut Einstellung)

Bei positivem Erfolgserlebnis gehts weiter in der Eruierung:

In den Kommandomodus wechseln
also:
RS auf low
Enable auf high
ldi temp, C0
out ausgabeport, temp
nop wie gehabt (oder Verzögerungsroutine aufrufen...)
enable auf low
wieder nops

In Datenübernahmemodus wechseln

RS auf high
enable auf high
ldi temp, 0x42
out ausgabeport, temp
nops
enable auf low
RS kann vorerst so stehen bleiben

Ergebnis:
Buchstabe B am Anfang der "dritten" Zeile

Analog dazu kannst Du die Adressen des Display-Rams direkt ansteuern, steht in der Doku,
welche Adressen es genau sind.
Du kannst natürlich auch einen "verbotenen" Adressbereich ansteuern, nur siehst Du dann nichts.
Logo.
Ist bei mir nämlich so gewesen.


Schau auch mal hier:
http://www.avr-praxis.de/forum/showthread.php?p=1005#post1005

scroll Dich mal durch bis unten, wo das Proggi mit dem "Groschengrab" ist.


Es grüßt

Oskar01
 
Prog 4 Zeilen LCD Initialisierung

Hallo @Y...,
hier noch das Proggi.
OK.
für KS0073-Controller geschrieben,
müsste aber auch bei anderen Controllertypen gehen. Deren Unterschiede beziehen sich im Wesentlichen auf die Timingbedingungen. Da gibt es welche, die benötigen zwischen den ersten Hex 30 jeweils unterschiedliche Wartezeiten, die von 160 ms bis mindestens 39 ys in den Dokus angegeben sind. Der KS-Typ soll sogar ohne die "Abra-Kadabra dreimal -Hex 30- schwarzer Kater" auskommen. Dazu muß ich noch was anmerken, doch.
Der eigentliche Witz dabei ist, daß das "F" im Function Set nun nicht zur Pixelung-Umschaltung dient, bzw. für die andere Darstellung der Dots-Anzahl, sondern hierbei in der Tat etwas mit der Zeilenzahl zu tun hat.
Ferner hatte ich oben Hex C2 noch im Kopf, muß natürlich Hex 2C heißen.
Dann die Hex 09.
Das sind die fundamentalen Unterschiede zu den "normalen" zweizeiligen Displays, die im Prinzip aber von der Adressenanwahl der Kolumnen kaum einen Unterschied aufweisen, nur eben nicht darstellen. Die arbeiten IMHO allesamt mit dem Extension-Driver für den Controller, nur bleibt dort, wie gesagt, der "verbotene" Adressbereich im "virtuellen Raum" stecken, bzw. wenn ich statt Hex 28 Hex 2C eingebe, ändert sich bei meinem 16x2-Display nichts.

Mir ist noch schleierhaft, wozu Du zwei Enable-Impuls-Muster benötigst, gibt es tatsächlich im Pinout Deines Displays da Unterschiede? Vielleicht ist das Busy-Bit sogar hardwaremäßig bei Deinem Display als Extra-Pin auch noch herausgeführt? Das erleichterte die Sache doch ganz ungemein.


Gib mal Bescheid, ob es bei Dir so funktioniert.
Würde dann vorschlagen, im Sinne der Übersichtlichkeit und erleichterten Suchfunktion im Forum eventuell einen neuen Thread zum Beispiel mit dem Titel "4-Zeilen-LCD-Initialisierung" aufzumachen.


Viel Spaß....

schönen Rest-Sonntag noch....

Es grüßt,
Oskar01

Anmerkung zu "Abra-Kadabra" oben.
Die Displays können zu jedem beliebigen Zeitpunkt nach Init in den Kommando-Modus wechseln und völlig anders aufgesetzt werden für diverse Effekte.
Fest steht, es soll immer ein Wechsel dann stattfinden zum Beispiel von Vier-Bit-Modus zu Acht-Bit-Modus.
Da ist zwingend vorgeschrieben. Daher das "Relikt" "Abra Kadabra". Obwohl ich das garnicht brauche, wenn ich stets im Acht-Bit-Modus arbeite.
Habs bei Vier-Bit-Modus ausprobiert, da ist es eine unbedingt notwendige Bedingung.
Dann gibt es noch Differenzen in den gängigen Lehrmeinungen, die allen Ernstes behaupten,
man könne sich das Hex 20 mit nachfolgendem Hex 28 für Init des Vier-Bit-Modus einsparen, weil Hex 20 zunächst einzeilig bedeutet, Hex 28 dann zweizeilig. Für unser Beispiel also wäre dieser Lesart zufolge, die Init-Sequenz dreimal Hex 38 also durchaus korrekt, genau so, wie Du es ja angegeben hattest.
Meine Wenigkeit steht aber dieser orthodoxen Meinung durchaus kritisch gegenüber.
Es hieße im Umkehrschluß nämlich, daß es allein genüge, das zweite Bit im "oberen" Nibble zu setzen, woraufhin der Controller automatisch nach einem Enable-Impuls verlangte, um dann das "untere" Nibble mit weiterem Enable-Impuls zu erwarten, um intern dann das Byte wieder richtig zusammenzusetzen. Das Kommando Hex 28 würde also im Controller gleich mehrere Funktionen auslösen. Er ist aber noch garnicht im Vier-Bit-Modus drin, also durchaus paradox.
Das könnte gründlich schiefgehen, bin ich der Meinung, und bleibe bei meinen Hex 20 zunächst, dem dann mindestens einmal - manchmal sogar zweimal - hintereinander das Hex 28 folgt.
Zurück zu Deinem Beispiel:
Das hieße nämlich, sende lieber dreimal "Abra Kadabra" Hex 30, gib dem Controller (bzw. den Controllern) nur "eine" Aufgabe zunächst, und sende dann erst Hex 3C anstelle von Hex 38, was ja "nur" zweizeilig bedeutete, bzw. Hex 2C, falls Du Erfahrungen mit dem Vier-Bit-Modus sammeln möchtest.
 

Anhänge

  • 4ZeilenLCD.txt
    4,4 KB · Aufrufe: 48
  • 4ZeilenLCDhex.txt
    885 Bytes · Aufrufe: 25
Vielen Dank erst einmal für deine Mühen.
Ich habe sehr viele Codes probiert, auch deinen letzten hier, aber das Display bleibt sturr und zeigt die 1. und 3. Zeile als schwarzen Balken an egal welchen Code ich nehme. Vielleicht liegt es auch drann das ich 2 Enableleitungen habe am Display. Ich schätze einmal das es als 2 Displays angesprochen werden muss, aber meinem Code gelingt es nicht das zu realisieren.
 
Zwei-in-einem-Display

Hallo @Y...
habe mir das Datenblatt runtergeladen.
Es werden KS0066-kompatible Display-Controller und -73-er als Extension- Driver verwendet.
Zum Test müßte einer der Controller zumindest zwei Zeilen - zunächst mal egal welche, irgendwie ansprechen.

Ändere das Proggi also ab in
3x Hex 30
Hex 38
Hex 38
Hex 01
Hex 02
Hex 06
Hex 0E
....mit den Warteschleifen dazwischen. Evtl. kürzere Schleifen immer wiederholt reinprogrammieren, wie gesagt 10 oder 20 mal, die direkt hintereinander abgearbeitet werden sollten.
Beispiel:

RS low
ldi temp, 0x30
out ausgabe, temp
nop
Enable high
nop
....
nop
Enable low
nop
...
RS low
ldi temp1, 0xFF
rcall Wait
nop
ldi temp1, 0xFF
rcall wait
nop
ldi temp1, 0xFF
rcall wait
nop
..
Wait:
dec temp1
cpi temp1, 1
brlt wait
ret
;und die ganze Suite des LCD-Init..

;am Ende
rjmp Enableschleife

Enableschleife:
nop
Enable high
nop
...
nop
Enable low
nop
rjmp Enableschleife


Probiere jeweils nur einen der zwei Enable-Eingänge aus. Auf keinen Fall einfach parallelschalten, das müßte hernach noch mit der Software geregelt werden, ein weiterer Portausgang für den zweiten Enable vorgesehen werden.

Dann ist mir noch aufgefallen, daß die LCD-Versorgungsspannung relativ hoch ist. Bei den anderen liegt die nur bei ca. 1,5 Volt, hier bei fast 4,5 Volt.
Da sollte trotzdem noch ein Poti vorgesehen sein. (zwischen 0 Volt und 5 Volt und ein kleiner Widerstand in Reihe, damit Du in Endstellung nicht über die Maximalspannung kommst. Schleifer an die LCD-Versorgungsspannung.)
Eventuell da mal dran drehen. Läßt sich der Kontrast überhaupt so einstellen?

Laut Datenblatt wird keine negative Vorspannung für LCD benötigt.

Sende dann nur mal eine Endlosschleife von Enableimpulsen mit Warteschleifen.
Da muß sich dann was tun.
Schwarze Balken und/oder flitzender Cursor.

Die Adressbereiche unterscheiden sich nicht von den "normalen" Displays.
Der zweite Controller verwendet dieselben Adressen,
Du hast also ein "Zwei-in-einem-Display", das sich
zunächst wie die anderen üblichen softwaremäßig behandeln ließe und den Hex 3C-String etc. nicht braucht.


Gruß von Oskar01
 
Sorry aber ich brauch immer recht lange bis ich verstanden habe was du meinst, merke das ich wohl viel zu lange wieder raus bin aus der Thematik.

Also ich denke das ich noch immer in der Initialisierung stecke da das Display beim einschalten die erste und dritte Zeile als schwarzen Balken darstellt und sich sonst nichts weiter tut. Egal was ich mache, die Balken bleiben bestehen.

Ja über Pin 12 kann ich den Kontrast einstellen (mit 10k Poti). Das Backlight wird mit 4,2 V betrieben aber derzeit lasse ich es noch aus und versuche das Display zur Zusammenarbeit zu bewegen.
 
Gratulation schon mal

Hallo @Y...,
Gratulation, Kontrast ist einstellbar.:)
Das ist der erste Schritt zum Erfolg.
Jetzt sollten nochmals genauestens das Pinout und die "Verdrahtung" unter die Lupe genommen werden.

Im dritten Schritt, wenn es dann immer noch nicht funktioniert, müßte ein Oszilloskop her, damit auch überprüft werden kann, ob der MC auf der richtigen Takt-Frequenz arbeitet, ob die Impulse auch tatsächlich da hinkommen, wo sie hinsollen, und wie sie so im allgemeinen und überhaupt aussehen.



Gruß von Oskar01
 

Anhänge

  • Impulse.png
    Impulse.png
    13,3 KB · Aufrufe: 15
Hallo Oskar,

also ich habe den Code mal meiner Hardware angepasst und festgestellt das die Schleifenverzögerung2 eine Endlosschleife war und das nach dem dritten Durchlauf nicht zur Initialsierung gesprungen wurde sondern sie wurde übergangen.

Aber leider hat sich noch immer nichts geändert ich habe auch einmal die Hardware nochmals überprüft. Auch das war ohne Ergebnis. Ich möchte dich bitten einmal über den Code zu schauen. Ich bin ihn im Debugmodus durchgegangen und eigentlich sollte es jetzt gehen.

Code:
;Initialisierungstest fuer LCD-Anzeige
;mit KS0066U-kompatiblem Controllerchip
;8-Bit-Mode; 4-Zeilen
;Daten-/Steuerbits auf PORTA, Bit D0 bis D7
;Enableimpuls erster Controller auf PORTC, Bit D0 
;RS-Impuls auf  PORTC, Bit D1
;Enableimpuls zweiter Controller auf PORTC, Bit D2
;R/WQuer auf Masse fest verdrahtet;
;Routine wird einmal durchlaufen und
;sistiert dann beim Label "Schleife" 
;mit Ausgabe TEXT*TEXT*TEXT* etc... 
;CPU Takt 1 MHz

.nolist
.include "m128def.inc"
.list

.def zeit = r16
.def zeit1 = r17
.def zeit2 = r18
.def temp = r19
.def temp1 = r20

.equ daten = porta
.equ impuls = portc



;Stack Initialisierung:

	ldi	temp, low(ramend)
	out	SPL, temp
	ldi	temp, high(ramend)
	out	SPH, temp

;Initialisierung; Datenrichtungsregister auf 8-Bit-Breite
;setzen und interne Pull-up-Widerstaende aktivieren:

	ldi	temp, 0xFF
	out	ddra, temp
	ldi	temp, 0xFF
	out	ddrc, temp
	rjmp	Start

Start:

	rcall	Einschaltverzoegerung
;	rcall	LCD_Initialisierung
	rjmp	Hauptprogramm

Einschaltverzoegerung:

	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	rcall   LCD_Initialisierung

Hauptprogramm:

	rcall	Text_Ausgabe

LCD_Initialisierung:

;LCD Reset, Acht-Bit-Modus initialisieren:

	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross	;Aller guten Dinge sind drei

;Zeilenzahl vier, Display einschalten:

	ldi	temp,	0b00110000	;Extension D/L, N "und" F 
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
		
;Anzeige ON/OFF Control definieren:

	ldi	temp,	0b00001000	;Display off, 4-zeilig ein
	out	daten, temp		;"und" Hex01 => 4 Zeilen
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	
;Anzeige ON/OFF Control definieren:

	ldi	temp,	0b00110000	;4-zeilig wieder aus
	out	daten, temp		;Acht-Bit-Modus ein	
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	nop

;Entry Mode Set:
	
	ldi	temp,	0b00000110	;Cursor increment, no shift
	out	daten, temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross

;Cursor move, display shift:
	
	ldi	temp,	0b00000110	;Cursor increment, no shift
	out	daten, temp		;Diese Aktion wird jedesmal ohne
	sbi	impuls, 0		;Schreib-Lese-Funktion
	rcall	Verzoegerung		;ausgeführt
	cbi	impuls, 0		;dient zur "Suchfunktion"
	rcall	Verzoegerung_gross	;und, um den Inhalt zu "lesen"
					;kann also hier auch wegfallen
	
;Display on, cursor on:
	
	ldi	temp,	0b00001111	;Cursor on/increment, no blink
	out	daten, temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross

;Display clear, cursor home:
	
	ldi	temp,	0b00000001	;es werden "space", Hex 20
	out	daten, temp		;in alle Display-RAM-Stellen
	sbi	impuls, 0		;geschrieben, dauert laenger
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	ret	

Text_Ausgabe:

	nop	
	sbi 	impuls, 1
	sbi	impuls, 0
	ldi	temp1, 'T'
	out	daten, temp1
	rcall	Verzoegerung
	nop
	nop
	cbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 1
	sbi	impuls, 1
	sbi	impuls, 0
	ldi	temp1, 'E'
	out	daten, temp1
	nop
	rcall	Verzoegerung
	nop
	cbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 1
	sbi 	impuls, 1
	sbi 	impuls, 0
	ldi	temp1, 'X'
	out	daten, temp1
	rcall	Verzoegerung
	nop
	cbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 1
	sbi	impuls, 1
	sbi	impuls, 0
	ldi	temp1, 'T'
	out	daten, temp1
	nop
	rcall	Verzoegerung
	nop
	cbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 1
	sbi	impuls, 1
	sbi	impuls, 0
	ldi	temp1, '*'
	out	daten, temp1
	nop
	rcall	Verzoegerung
	nop
	cbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 1
	rcall	Verzoegerung_gross
	nop
	ret

Verzoegerung: ; nc=[1+6x(255-1)+5]=6x{255}=0,3825 ms

	ldi	zeit, 0xFF

Verzoegerungs_Schleife:

	dec	zeit 
	cpi	zeit, 1
	brlt	Verzoegerungs_Schleife
	ret

Verzoegerung_gross: 

	ldi zeit, 0xDF
	ldi zeit1, 0x89
;	ldi zeit2, 0xFF
	rjmp Verzoegerungs_Schleife2

Verzoegerungs_Schleife2: 
	
	dec	zeit 
	cpi	zeit, 1
	brlt	Verzoegerungs_Schleife2
	ldi zeit, 0xFF
	dec	zeit1
	cpi	zeit1,	1
	brlt	Verzoegerungs_Schleife2
;	ldi zeit1, 0xFF
;	dec	zeit2
;	cpi	zeit2,	1
;	brlt	Verzoegerungs_Schleife2
;	nop
	ret
 
Hallo @Y...

;Zeilenzahl vier, Display einschalten:

ldi temp, 0b00110000 ;Extension D/L, N "und" F
out daten, temp
muß 0b00111000 oder Hex 38 lauten für zweizeilig, F kannst Du jetzt erstmal weglassen.

Sind die Portzuweisungen auch richtig gewählt?

Gruß Oskar01...
 
Ich habe mir nochmals das Signaldiagramm genauer angeschaut, kann es sein das das Display eine fallende Flanke nach jedem Hex 30 benötigt?
 
Ich habe mir nochmals das Signaldiagramm genauer angeschaut, kann es sein das das Display eine fallende Flanke nach jedem Hex 30 benötigt?

Hallo @ Yankee,

Hallo @ Yankee,
Die Idee mit dem Toggeln des RS-Impulses hatte ich auch irgendwo gelesen, brachte aber im Endeffekt garnichts. Auch das "Null-Setzen" des Ausgabeports wird schlichtweg ignoriert. Wird aber in anderem Zudsammenhang gebraucht , wenn man selber Charakters erzeugen will, aber soweit sind wir ja noch nicht....
Daher auch dieses Oszillogramm, das zeigt, wie kurz 250 Nanosekunden sind im Vergleich zu den anderen Signalen. Hier ist nur der cbi für das RS-Bit hinter der Datenübernahme mal dargestellt unten, nur ein Lichtpunkt.

Wenn Du natürlich den Enableimpuls meinst, dann auf jeden Fall, der muß rein, denn sonst wird weder ein Kommando noch eine Übernahme von Daten, die auf dem Display angezeigt werden sollen, stattfinden. Das ist schon klar.



Also, meine Idee nun,
da die erste Hürde genommen ist, das Display die Segmente unterschiedlich kontrastieren kann, man auch keine negative Spannung anlegen muß,
was ich zunächst befürchtete,

geht es zunächst nochmals an die Hardware:

Nehme an, es wird auch mit dem EVA-Board STK500 gearbeitet, bzw, mit einem der ATMega8xxx-er-Serie-MC.

Du hast Dich von der Portzuweisung, sowie vom richtigen Pinout, bzw. Anschluß überzeugt, evtl. alle Leitungen mal "durchgeklingelt", um irgendwelche Wackelkontakte auszuschließen,

dann muß der Code untersucht werden.

Hier "reme" mal bitte alles weg in dem 8-Bit-Text-Test-Proggi,
laß nur die Assemblerdirektiven, Stackinitialisierung, Portinitialisierung und die Zeitschleifen mit der Einschaltverzögerung drin. Es sollte dann nur dreimal Hex30 und einmal Hex 38 mit dem RS vorher auf low und dem Enableimpuls, sowie der großen Verzögerung -ok- auch mal drinbleiben.

Schalte die Versorgungsspannung ein, dann müssten für ca. 1 Sekunde zwei Zeilen (also Zeile 1 und 3, bzw. 2 und 4, wenn der andere Enable-Eingang genommen wurde) alles schwarze Balken bekommen.
Dabei dreh die Intensität des Kontrastes nicht schon vorher so hoch, daß kein Unterschied mehr zu erkennen ist, dreh den Kontrast also soweit runter, daß geradesoeben noch die Segmente zu erkennen sind, wenn kein MC angeschlossen ist.


Kommt das nicht direkt, drücke mal die Resettaste am MC.

Und?


Bin mal gespannt.


Fortsetzung folgt.

Gruß
von Oskar01
 
Hallo Oskar,

dein Tip mit dem Kontrast war sehr gut, ich hatte den voll aufgedreht und daher nur schwarze Balken gesehen. Also jetzt zeigt er mir in der ersten Zeile *(Winkel oben rechts) *T. also demnach sollte die Initialisierung jetzt funktionieren. *endlich.

So dann geht es jetzt wohl an die eigendliche Sache das Display "tanzen" zu lassen.
 
Gratulation.....

Herzlichen Glückwunsch, @Y...,
es hat geklappt.

Möchte hier nochmal auf die Bedeutung der einzelnen "Initialisierungsstufen" eingehen, wenn's nicht langweilt.
Steht zwar alles in den Datenblättern, aber oft halt nur in Englisch und irgendwie mißverständlich formuliert.

Die Abfollge der Befehle scheint oft auch eine Bedeutung zu spielen, die man oft unterschätzt.
Der eigentliche Code scheint mir dagegen überhaupt nicht unterschiedlich zu sein zwischen den HD44780 und KS0066 bzw. ST7066 etc. -Controllern.

Wo liegt nun der Haken?

OK.
Das versuchte ich seit drei Monaten schon herauszufinden.

Also,
numero eins,
die dreimal hintereinanderzusendenden Hex 30.
Das ist der Reset, der auch als Teil des Function Sets (Datenlänge-8/4Bit-Zeilenanzahl-Zusatzfeatures(Zeichensatz-Dot-Anzahl) angesehen werden kann,
wobei einige Hersteller sich diese Sequenz einsparen und direkt schon die
Bits für den vollständigen Function Set setzen. Hier also Hex 38.

Das ist die niedrigste Stufe, die bei der Initialisierung durchlaufen werden muß.
Sollte hinterher im Programm an Zeilenzahl und Datenlänge etwas geändert werden , geht das nur über den Function Set, da muß dann wieder von vorne begonnen werden.


Dann kommt der nächste Schritt, Display on/off Control.
OK. Hier sage ich dem Display, ob es ein- oder ausgeschaltet werden soll, ob ich den Cursor-Unterstrich und den abwechselnd hell/dunkel komplementär blinkenden Charakter auf der Cursorposition bzw. eine Stelle davor haben möchte. Der Witz ist, nach dem Power-On-Self-Reset initialisiert sich das LCD von selbst auf 8-Bit-,Cursor nach rechts, eine bzw. zwei Zeilen aber schaltet sich sinnigerweise selbst wieder ab.
Also ich brauche diesen Befehlssatz auf jeden Fall.



Jetzt könnte ich direkt auch, da ich mich entschieden habe, ob ich einen Cursor dargestellt haben möchte oder nicht in den Entry Mode Set wechseln.
Da wird dann noch differenziert, wierum der Cursor laufen soll, ob der Displayinhalt
geschoben werden soll, also Cursor scheint zu stehen, nur der Text scrollt durch.


Das sollte ich aber nicht tun, bevor nicht der Cursor an den Anfang gesetzt wurde und die Schneeflocken und zufälligen Dots auf dem Display mit dem Befehlssatz Display Clear in dem DDRAM geputzt wurde.

(Ja, ja, Scheeflocken hatte ich auch schon, also einzene tanzende Pixel im Display, oder das sich wie bei der Bierreklame auffüllende Segmentmuster.)

Also vor Entry Mode Set der Display Clear Befehlssatz, wobei der Controller beim Display Clear meistens anfängt zu asten, sollte man ihm eine grölßere Pause vergönnen, bevor man in den Entry Mode Set wechselt.


Die weiteren Befehle Hex02 für Cursor Home ohne Display-Inhalt zu löschen oder der Shift -Set sind vorerst nicht unbedingt nötig, das sind Befehlssätze, die für die Programmierung hinterher wichtig sind, für die Initialisierungsroutine also nicht unbedingt gebraucht werden.


So,
es freut mich,
daß es geklappt, hat,
jetzt macht es wieder richtig Spaß, gelle?

Gruß von Oskar01
 
Hallo Oskar,

also egal was ich nach der Initialisierung aus remme, das Display zeigt immer dasselbe an

Picture 53.jpg


Der Code schaut derzeit so aus
Code:
;Initialisierungstest fuer LCD-Anzeige
;mit KS0066U-kompatiblem Controllerchip
;8-Bit-Mode; 4-Zeilen
;Daten-/Steuerbits auf PORTA, Bit D0 bis D7
;Enableimpuls erster Controller auf PORTC, Bit D0 
;RS-Impuls auf  PORTC, Bit D1
;Enableimpuls zweiter Controller auf PORTC, Bit D2
;R/WQuer auf Masse fest verdrahtet;
;Routine wird einmal durchlaufen und
;sistiert dann beim Label "Schleife" 
;mit Ausgabe TEXT*TEXT*TEXT* etc... 
;CPU Takt 1 MHz

.nolist
.include "m128def.inc"
.list

.def zeit = r16
.def zeit1 = r17
.def zeit2 = r18
.def temp = r19
.def temp1 = r20

.equ daten = porta
.equ impuls = portc



;Stack Initialisierung:

	ldi	temp, low(ramend)
	out	SPL, temp
	ldi	temp, high(ramend)
	out	SPH, temp

;Initialisierung; Datenrichtungsregister auf 8-Bit-Breite
;setzen und interne Pull-up-Widerstaende aktivieren:

	ldi	temp, 0xFF
	out	ddra, temp
	ldi	temp, 0xFF
	out	ddrc, temp
	rjmp	Start

Start:

	rcall	Einschaltverzoegerung
;	rcall	LCD_Initialisierung
	rjmp	Hauptprogramm

Einschaltverzoegerung:

	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	rcall   LCD_Initialisierung

Hauptprogramm:

	rcall	Text_Ausgabe

LCD_Initialisierung:

;LCD Reset, Acht-Bit-Modus initialisieren:

	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	ldi	temp,	$30
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross	;Aller guten Dinge sind drei

;Zeilenzahl vier, Display einschalten:

	ldi	temp,	0b00111000	;Extension D/L, N "und" F 
	out	daten,	temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
		
;Anzeige ON/OFF Control definieren:

	ldi	temp,	0b00001000	;Display off, 4-zeilig ein
	out	daten, temp		;"und" Hex01 => 4 Zeilen
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross

;Anzeige ON/OFF Control definieren:

	ldi	temp,	0b00111000	;4-zeilig wieder aus
	out	daten, temp		;Acht-Bit-Modus ein	
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	nop

;Display clear, cursor home:
	
	ldi	temp,	0b00000001	;es werden "space", Hex 20
	out	daten, temp		;in alle Display-RAM-Stellen
	sbi	impuls, 0		;geschrieben, dauert laenger
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross
	rcall	Verzoegerung_gross
	ret	
		
;Entry Mode Set:
	
	ldi	temp,	0b00000111	;Cursor increment, no shift
	out	daten, temp
	sbi	impuls, 0
	rcall	Verzoegerung
	cbi	impuls, 0
	rcall	Verzoegerung_gross

;Cursor move, display shift:
	
;	ldi	temp,	0b00000110	;Cursor increment, no shift
;	out	daten, temp		;Diese Aktion wird jedesmal ohne
;	sbi	impuls, 0		;Schreib-Lese-Funktion
;	rcall	Verzoegerung		;ausgeführt
;	cbi	impuls, 0		;dient zur "Suchfunktion"
;	rcall	Verzoegerung_gross	;und, um den Inhalt zu "lesen"
					;kann also hier auch wegfallen
	
;Display on, cursor on:
	
;	ldi	temp,	0b00001111	;Cursor on/increment, no blink
;	out	daten, temp
;	sbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 0
;	rcall	Verzoegerung_gross



;Text_Ausgabe:

;	nop	
;	sbi impuls, 1
;	sbi	impuls, 0
;	ldi	temp1, 'T'
;	out	daten, temp1
;	rcall	Verzoegerung
;	nop
;	nop
;	cbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 1
;	sbi	impuls, 1
;	sbi	impuls, 0
;	ldi	temp1, 'E'
;	out	daten, temp1
;	rcall	Verzoegerung
;	nop
;	nop
;	cbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 1
;	sbi impuls, 1
;	sbi impuls, 0
;	ldi	temp1, 'X'
;	out	daten, temp1
;	rcall	Verzoegerung
;	nop
;	nop
;	cbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 1
;	sbi	impuls, 1
;	sbi	impuls, 0
;	ldi	temp1, 'T'
;	out	daten, temp1
;	rcall	Verzoegerung
;	nop
;	nop
;	cbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 1
;	sbi	impuls, 1
;	sbi	impuls, 0
;	ldi	temp1, '*'
;	out	daten, temp1
;	rcall	Verzoegerung
;	nop
;	nop
;	cbi	impuls, 0
;	rcall	Verzoegerung
;	cbi	impuls, 1
;	rcall	Verzoegerung_gross
;	nop
;	ret

Verzoegerung: ; nc=[1+6x(255-1)+5]=6x{255}=0,3825 ms

	ldi	zeit, 0xFF

Verzoegerungs_Schleife:

	dec	zeit 
	cpi	zeit, 1
	brlt	Verzoegerungs_Schleife
	ret

Verzoegerung_gross: 

	ldi zeit, 0xDF
	ldi zeit1, 0x89
;	ldi zeit2, 0xFF
	rjmp Verzoegerungs_Schleife2

Verzoegerungs_Schleife2: 
	
	dec	zeit 
	cpi	zeit, 1
	brlt	Verzoegerungs_Schleife2
	ldi zeit, 0xFF
	dec	zeit1
	cpi	zeit1,	1
	brlt	Verzoegerungs_Schleife2
;	ldi zeit1, 0xFF
;	dec	zeit2
;	cpi	zeit2,	1
;	brlt	Verzoegerungs_Schleife2
;	nop
	ret

Ich habe keine Ahnung wo die Daten her kommen die er dort anzeigt, weil eigendlich sollte das Display doch jetzt leer sein und der Cursor oben links.
Habe es auch schon versucht den MC zu löschen und neu zu programmieren. Hat aber leider auch nichts gebracht.

Also langweilen kannst du mich damit garnicht, das ist mein erstes Display und da will ich doch auch so viel wie möglich lernen und verstehen.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)