Hallo,
ich arbeite mich langsam durch das AVR Tutorial.
Mit dem LCD habe ich nun arge Probleme und suche hier Hilfe.
Habe mir ein DOGM163S-A bestellt und bin nun seit Tagen am verzweifeln.
Das Thema wurde schon vielfach besprochen. Habe lange im Forum
gelesen, trotzdem finde ich meinen Fehler nicht.
Wäre nett, wenn jemand meinen Code ansehen könnte, um mir einen
Tipp zu geben.
Ich Programmiere im AVR Studio in Assembler. C-Code verstehe ich noch
nicht.
Habe einen ATmega8 auf einem STK600, ext. Takt ca. 4MHz.
Das LCD habe ich wie im Datenblatt für 5V 4-Bit beschaltet.
R/W ziehe ich auf GND und Reset auf +5V.
D4-D7 habe ich auf PORTD0-3, RS auf PORTD4 und E auf PORTD5 gelegt.
So wird es im Tutorial ja auch beschrieben.
Hintergrundbeleuchtung ist C1/C2 A1/A2 parallel mit ca. 33 Ohm
Vorwiderstand an 5V. Das ist das einzige, was funktioniert :)
Auf dem LCD tut sich absolut überhaupt nichts.
Vielleicht könnte auch jemand ein .hex zur Verfügung stellen,
damit ich einen Hardware Fehler / Fehler bei der Beschaltung
ausschließen kann?
Habe das Initialiesierungsprotokoll des Datenblatts versucht umzusetzen.
Meist findet sich ja hier oder in den Timings der Fehler, aber ich finde
es nich. In der Simulation mit AVR Studio sieht es eigentlich auch gut
für mich aus.
Kann mir bitte jemand helfen. Das frustet mich.
Gruß Marcus
1
.include "m8def.inc"
2
3
ldi r16,LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
4
out SPL, r16
5
ldi r16,HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
6
out SPH, r16
7
8
ldi r16, 0xFF
9
out DDRD, r16 //Port D = Ausgang
10
11
rcall LCD_init
12
rcall LCD_clear
13
14
ldi r16, $45 ; Zeichen anzeigen
15
rcall lcd_data
16
17
loop:
18
rjmp loop
19
20
; Daten an LCD senden
21
LCD_data:
22
mov r17,r16 //r17 in r16 kopieren
23
swap r16 //oberes gegen unteres Nibble tauschen
24
andi r16, 0b00001111 //nur das untere übernehmen
25
sbr r16,0b00010000 //RS (PORT D4) auf high
26
out PORTD, r16 //erstes Nibble wurde übertragen
27
rcall LCD_enable
28
29
andi r17, 0b00001111 //zweites Nibble (r17), nur das untere übernehmen
30
sbr r17, 0b0001000 //RS (PORT D4) auf high
31
out PORTD, r17
32
rcall LCD_enable
33
rcall delay26us
34
ret
35
36
;Einen Befehl ausführen (ohne sbr r16,1<<4 (RS auf low))
37
LCD_command:
38
mov r17,r16 //r17 in r16 kopieren
39
swap r16 //oberes gegen unteres Nibble tauschen
40
andi r16, 0b00001111 //nur das untere übernehmen
41
out PORTD, r16 //erstes Nibble wurde übertragen
42
rcall LCD_enable
43
44
andi r17, 0b00001111 //zweites Nibble (r17), nur das untere übernehmen
Marcus Scholz schrieb:> ...> Habe einen ATmega8 auf einem STK600, ext. Takt ca. 4MHz.> ...> ;Delay Schleifen bei 4MHz Taktfrequenz> ...
Dieser Sache würde ich als erstes nachgehen. Die Delay müssen stimmen,
da hilft kein "ca.". Zur Not ein Blinkprogramm für'ne LED schreiben und
den Puls des Kleinen messen...
Ein beliebtes Problem ist auch die Kontrasteinstellung des LCD. Link zum
Datenblatt wäre vielleicht auch hilfreich, wenn andere das Timing
überprüfen wollen/sollen.
Bei den DOGM musste sehr genau auf die Zeiten achten, die das Display
zur Ausführung der Befehle braucht, z.B der Clear/REturn Home braucht in
etwa 1 ms anstatt der bei dir erwähnten 26us.
Also ich fang bei ner Initialisierung immer so an, dass ich die
Wartezeiten und Delays großzügig ausleg, damit man einfach sehr schnell
ein funktionierendes Display hat.
Sobald es läuft kann man die Zeiten stückchenweiße reduzieren.
Auch die Enable-Zeit würd ich länger machen, vorm Enable kurz warten,
dahinter auch wieder kurz warten.
Hallo,
ersteinmal vielen Dank für die rege Unterstützung!!
Anbei poste ich die Datenblätter.
Die Timings werde ich mir noch genauer ansehen.
Mit den Delays habe ich Probleme gehabt, diese auszurechnen.
Habe so gerechnet: 4MHz, sind 25nS pro Takt. Dann benötige ich
1,6Mio. Takte für z.B. 40mS. Diesem Wert habe ich mich dann in der Delay
Schleife angenähert. Dabei 3 Takte für 'brne' und 'dec' * der Anzahl der
Durchläufe gerechnet. Diesen Wert dann ein weiteres Mal multipliziert
mit der äußeren Schleife.
Wie wird das Richtig gemacht? Habt ihr einen Link, wo es genauer erklärt
wird?
Werde einen weiteren Port schalten, der ein Reset sendet. Danke für den
Tipp Peter. Meine Delays werde ich auch großzügiger auslegen.
Hoffentlich kann ich dann bald eine Erfolgsmeldung berichten.
Gruß Marcus
Hallo,
das LCD bleibt leider ohne Reaktion.
Habe eure Vorschläge so gut ich kann umgesetzt:
Habe jetzt auf PORTB0 das RESET (PIN40) gelegt.
Anfangs ziehe ich es für 10ms auf high, dann für 100ms auf low und dann
belasse ich es auf high. Warte wieder 100ms und beginne dann mit der
Initialisierung.
Die Timings zwischen den einzelnen Inits habe ich mal alle auf je 1ms
gesetzt. Dass ist doch mehr als genug, oder?
Könnt ihr mir noch weitere Tips geben, was ich falsch gemacht habe?
Danke nochmals.
Gruß Marcus
Anbei der geänderte Code:
1
.include "m8def.inc"
2
3
.EQU TAKT = 4001728 ;Systemtakt
4
5
ldi r16,LOW(RAMEND) ; LOW-Byte der obersten RAM-Adresse
6
out SPL, r16
7
ldi r16,HIGH(RAMEND) ; HIGH-Byte der obersten RAM-Adresse
8
out SPH, r16
9
10
ldi r16, 0xFF
11
out DDRD, r16 //Port D = Ausgang
12
out DDRB, r16
13
14
rcall LCD_init
15
rcall LCD_clear
16
17
ldi r16, $45 ; Zeichen anzeigen
18
rcall lcd_data
19
20
loop:
21
rjmp loop
22
23
; Daten an LCD senden
24
LCD_data:
25
mov r17,r16 //r17 in r16 kopieren
26
swap r16 //oberes gegen unteres Nibble tauschen
27
andi r16, 0b00001111 //nur das untere übernehmen
28
sbr r16,0b00010000 //RS (PORT D4) auf high
29
out PORTD, r16 //erstes Nibble wurde übertragen
30
rcall LCD_enable
31
32
andi r17, 0b00001111 //zweites Nibble (r17), nur das untere übernehmen
33
sbr r17, 0b0001000 //RS (PORT D4) auf high
34
out PORTD, r17
35
rcall LCD_enable
36
ldi r16, 1
37
rcall warte1ms
38
ret
39
40
;Einen Befehl ausführen (ohne sbr r16,1<<4 (RS auf low))
41
LCD_command:
42
mov r17,r16 //r17 in r16 kopieren
43
swap r16 //oberes gegen unteres Nibble tauschen
44
andi r16, 0b00001111 //nur das untere übernehmen
45
out PORTD, r16 //erstes Nibble wurde übertragen
46
rcall LCD_enable
47
48
andi r17, 0b00001111 //zweites Nibble (r17), nur das untere übernehmen
Hi
>andi r17, 0b00001111 //zweites Nibble (r17), nur das untere übernehmen>sbr r17, 0b0001000 //RS (PORT D4) auf high>out PORTD, r17
Fehler in der zweiten Zeile
>//Function set> ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1> out PORTD, r16> rcall LCD_command
Was soll die Ausgabe auf PortD?
MfG Spess
Hallo,
Peter, ja CSB ist fest auf low.
Spess, in der zweiten Zeile fehlte eine Null.
Gut gesehen! :) - Danke!
Die Ausgabe auf PORTD war Unsinn, da diese
über LCD_command vorgenommen wird. Habe ich auskommentiert.
Das LCD tut leider immernoch nichts.
Hoffe ihr werdet mir noch weiter helfen.
Gruß Marcus
Hallo,
es klappt! Mehr oder weniger...
Das Display initialisiert.
Ich habe mit den Contrasteinstellungen noch rumgespielt.
Bei abgedunkeltem Raum, kann ich die Kästchen in den Zeilen erahnen,
sehe einen Cursor im dritten Feld blinken, im ersten einen Strich oben
im
zweiten einen Strich unten.
Bei Reset des ATmega kann es sein, dass das LCD initialisiert, oder
auch nicht, muss man öfters probieren.
Wenn es dann klappt, sieht man manchmal auch einen Buchstaben.
Ist immerhin ein Anfang und ich kann weiter probieren. Jetzt weiß ich,
dass der Schaltungsaufbau stimmt und die Pinbelegung passt.
Ich werde berichten...
Bin euch sehr dankbar für die Unterstützung!
Gruß Marcus
Hi
>Ist immerhin ein Anfang und ich kann weiter probieren. Jetzt weiß ich,>dass der Schaltungsaufbau stimmt und die Pinbelegung passt.
Überprüfe noch mal die deine Initialisierungswerte (habe ich nicht
gemacht).
Evtl. auch mal im Datenblatt des Controllers (vom Displays) nachsehen.
MfG Spess
Hallo,
das LCD verhält sich wirklich sehr zickig.
Wenn die Initialisierung nach mehrfachem Reset dann mal funktioniert
haben sollte, ist es sehr schlecht ablesbar. Die Kontrasteinstellungen
wirken sich nur minimal auf das LCD aus.
Lediglich wenn ich Pin25 von 5V abnehme und offen lasse, ist es
einigermassen gut lesbar. Aber das es so schlecht initialisiert nervt
wirklich.
Leider kann ich nicht herausfinden, wo mein Fehler genau liegt.
Habe die Initialisierung aus dem Datenblatt des LCD benuntzt.
Verschiedene
Einstellungen, Reihenfolgen und Timings probiert.
Auch mit den Parametern aus den diversen Forenbeiträgen scheint es nicht
wirklich zu funktionieren.
Habe mir jetzt erstmal ein anderes LCD bestellt, um mit dem Assembler
Lernen weiter zu kommen. In der Hoffnung, dass es damit einfacher wird.
Jedenfalls bedanke ich mich nochmals für Eure Hilfe. Danke!
Gruß
Marcus