PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LCD initialisieren



Spitfire
03.08.2012, 03:04
Hallo zusammen !!!

Ich bin gerade dabei, AVR-Tutorial bei http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD durchzuarbeiten. Jetzt ist es endlich soweit ein LCD anzuschließen. Nur ist da leider für einen Anfänger die erklärung recht schwer zu durchblicken. Ich habe im Netz zwar einiges gefunden, was mir aber bei meinem jetzigen Wissen über Assembler, Atmega und co. nicht recht hilfreich war. Ich benutze das Display Blueline Dotmatrix (EA W162B-N3LW) von Reichelt (http://such002.reichelt.de/?SID=13UBbXsX8AAAIAAAJdO3k729f9c8d5488f23088873d62 1565c65f;ACTION=446). Im Turtorial steht das
$3 und ein paar µs warten öfters im das Steuerregister geschrieben werden soll, aber wer, was wo :confused: ist das Steuerregister.

Ich habe es mit den angaben im Datenblatt (dem Display beigelegt, und bei Reichlt als download verfügbar) versucht. Hierbei soll folgendes am Port ausgegeben werden:

.........RS......RW.....DB7.....DB6........DB5...D B4
.........0........0........0.........0...........1 ......0...............4-Bit Datenlänge einschalten (noch im 8-Bit Modus)

RS = PD4
RW = PD5
DB7 = PD3
DB6 = PD2
DB5 = PD1
DB4 = PD0

Mit ldi r16, 0b00000010 soll bei der Ausgabe auf PD1 ein 1 ausgegeben werden. Der Rest sollte mit 0 belegt werden. Mit dem anschließenden out PORTD, r16 sollten die Ausgänge dementsprechend belegt werden.

Hier noch der gesammte Quelltext:

.include "m8def.inc"
.include "lcd-routines.c"

ldi r16, 0xFF
out DDRD,r16 ;Im Datenrichtungsregister PORTD als Ausgang deklarieren

ldi r16, 0b00000010
nop ;Dem Diplay Zeit geben um sich selbst zu initialisieren
nop
nop
nop
nop
nop
out PORTD, r16

nop ;Dem Diplay Zeit geben um sich selbst zu initialisieren
nop
nop
nop
nop
nop

ldi r16, 125 ;Ab dieser Zeile ist das Programm nur Abgeschrieben

mov r17,r16 ; Kopie von r16 in r17 eintragen

swap r16 ; vertauscht die beiden Nibbles von r16 (Die Bit´s 0-3 und 4-8 werden vertauscht)

andi r16, 0b00001111 ; Nur die vier unteren (mit 1 markierten)
; Bits werden übernommen, alle anderen werden null

sbr r16, 0b00010000 ; Bit 4 setzen, alle anderen Bits bleiben gleich

out PORTD, r16

sbi PORTD, 5 ;Den 5.PORTD (PD5) auf High setzen, um den Display zu Signalisieren, das es die Daten von PD0 bis PD4 übernehmen kann
nop ; 3 Taktzyklen warten, um dem Display, für die Datenübernahme, genügend Zeit zu geben
nop
nop
cbi PORTD, 5 ;PD5 wieder auf LOW setzen

andi r17, 0b00001111

sbr r17, 1<<4 ; nur eine andere Schreibweise von oben

out PORTD, r17

sbi PORTD, 5
nop
nop
nop
cbi PORTD, 5



Ich hoffe ihr könnt mir ein paar Tip´s zu initialisierung geben, und bitte nicht vergessen, ich stehe noch ganz am Anfang mit dem Assembler-Programmieren.

Danke für eure bemühungen !!:rolleyes:

Spitfire
03.08.2012, 09:21
Hallo zusammen !!

ICh habe natürlich weiter probiert, und den Code nochmal verändert:



ldi r18, 0b00010100 ;Dem Diplay Zeit geben um sich selbst zu initialisieren
ldi r16, HIGH(RAMEND)
out sph, r16
ldi r16, LOW(RAMEND)
out SPL, r16

rcall Warten

.....
.....
.....

Warten:
dec r18
brne Warten
ret




Eigentlich hat sich nur die Warteschleife, welche dem Display Zeit gibt um sich selbst zu initilaiseren, geändert. Hat aber nicht wirklich einen Unterschied gemacht.

Danke nochmals ;)

radbruch
03.08.2012, 16:19
Hallo

Takte der Befehle:

dec 1
brne 1/2
rcall 3
ret 4

In der Schleife 19*3 +2 (19 mal springen und einmal nicht springen) +3 +4 ergibt 66. Bei 16MHz-Takt bedeutet das 1Sekunde/16000000*66 oder 0,000004125s oder 4,125µs Verzögerung. Das scheint mir viel zu kurz, vor allem wenn "zähe" Funktionen wie clear oder cursorhome Ausführungszeiten im ms-Bereich haben. Auch den Hinweis rechts auf Seite drei des Datenblatts sollte man beachten. Ich habe mir die Wikiseite noch nicht angeschaut, aber ich vermute, du prüfst das busy nicht. Im Zweifel immer mit deutlich zu großer Verzögerung starten.

Link zum LCD: http://www.reichelt.de/Hintergrund-blau/LCD-162C-BL/3//index.html?ACTION=3&GROUPID=3006&ARTICLE=53941&SHOW=1&START=0&OFFSET=500&
Link zum Datenblatt: http://www.reichelt.de/index.html?;ACTION=7;LA=3;OPEN=0;INDEX=0;FILENAME= A500%252FLCD162CBL%2523EAS.pdf

Gruß

mic

[Edit]
Das LCD hat zwei Register. Ins Datenregister schreibt man die Werte, ins Steuerregister die Kommandos. Mit der R/S-Leitung wird zwischen Kommando und Daten unterschieden, ein Low bedeutet, die angelegten Signale an den Datenleitungen werden als Kommando interpretiert, ein High bedeutet, jetzt kommen Daten. Bei einer 4bit-Ansteuerung werden die Datenbytes in zwei Schritten übertragen, wenn ich mich recht erinnere zuerst das High- und dann das Lownipple.

Die Übernahme der angelegten Datenpegel steuert man mit dem E-Signal, bei einer Flanke nach Low werden die Pegel an den Dateneingängen eingelesen. Die Datenflußrichtung steuert man mit dem R/W-Signal, low bedeutet, ins LCD reinschreiben. Weil die einfachste Ansteuerung eines LCD ohne Auswertung des busy auskommt (und man sich so einen Pin am µC spart) kann man diese Leitung direkt mit GND verbinden.

Da das LCD natürlich nach dem Einschalten nicht weiß, ob es mit 4 oder 8 Bits angesteuert wird, startet es im 8bit-Modus. Deshalb muss man zu Beginn der Initialisierung zuerst auf 4 Bits umschalten. Das Kommando dazu lautet, formatiert für den 8bit-Modus, so:

0b0010 0000 (nach dem Beispiel im Datenblatt Seite 4)

Das bedeutet, diesen ersten Wert für das LCD muss man mit einer 8 Bit Ausgabefunktion senden. Beim Senden muss R/W auf Low für "Schreiben" und RS auf Low für "Kommando" gesetzt werden. Das eigentliche Senden läuft dann so ab:

E auf 0
RS auf 0

setzen und kurz warten, bis sich die Pegel eingestellt haben (tAS)

E auf 1

D4-D7 auf das Daten Highnipple

Wieder warten, bis sich die Pegel eingestellt haben (PWEH)

E auf 0

Jetzt hat das LCD die Daten übernommen und führt den Befehl aus. Günstig ist es, wenn man nun noch auf den Datenmodus zurückschaltet:

RS auf 1

Nach einer weiteren Wartezeit, bis TCYCE erreicht ist, ist das Senden fertig.

Ab jetzt erwartet das LCD alle weiteren Daten im 4 Bit-Format, ein Byte wird dann durch das einzelne Senden des High- und des Lownipples übertragen. Da der oben beschriebe Ablauf beim Senden auch ein Lownipple übertragen kann, packen wir es in eine Funktion der wir das auszugebende Nipple als Parameter übergeben:

send_nipple(nipple)

und ändern oben nach

D4-D7 auf das nipple

und senden die Initialisierung:

send_nipple(0b0010) 4-Bit Datenlänge einschalten (noch im 8-Bit Modus)

send_nipple(0b0010) 4-Bit Datenlänge, 1-zeiliges Display, 5x7 Font
send_nipple(0b0000)

send_nipple(0b0010) nochmal senden, weil manchmal nötig
send_nipple(0b0000)

send_nipple(0b0000) Display ein, Cursor ein, Cursor blinken
send_nipple(0b1111)

send_nipple(0b0000) Display löschen, Cursor auf 1. Spalte von 1. Zeile
send_nipple(0b0001)

send_nipple(0b0000) Cursor Auto-Increment
send_nipple(0b0110)

Jede Leerzeile zwischen den Sende-Aufrufen steht für eine Wartezeit die der Ausführungszeit des jeweils vorangegangenen Befehls entspricht. Für den groben Test würde ich mit 2ms pro Leerzeile anfangen...

Da send_nipple() nur Kommandos senden kann (RS ist beim Senden immer low) benennen wir es in send_kommando() um und erzeugen eine Kopie in der wir RS auf 0 in RS auf 1 ändern und an deren Ende wir eine kurze Verzögerung für die Darstellung des Zeichens anfügen und die wir anschliesend send_daten() nennen:

send_daten(114)
send_daten(103)
send_daten(104)
send_daten(55)
send_daten(124)
send_daten(145)
send_daten(163)
send_daten(164)

Ich hoffe,das funzt so.

Spitfire
03.08.2012, 23:18
Hallo Radbruch !!

Das Haut jetzt hin !!:p:p

Danke für deine Hilfe. Am Anfang habe ich mich zwar überhaupt nicht durchgeblickt, aber mit dem Studieren deiner Zeilen, und viel ausprobieren hat es aufeinmal geklappt. Jetzt werde ich nochmal den fertigen Code studieren, warum das so funktioniert. Aber dein Eintrag war eine sehr große Hilfe.

Danke nochmals

Spitfire