Forum: Mikrocontroller und Digitale Elektronik Newbie Probleme bei LCD DOGM Initialisierung in Assembler


von Marcus S. (msohz)


Lesenswert?

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
45
out PORTD, r17
46
rcall LCD_enable
47
rcall delay26us
48
ret
49
50
LCD_enable:
51
sbi PORTD, 5        //enable high
52
nop              //3 Taktzyklen warten
53
nop
54
nop
55
cbi PORTD, 5        //enable wieder low
56
ret
57
58
59
;Delay Schleifen bei 4MHz Taktfrequenz
60
delay26us:                               ; 26,3us Pause
61
           ldi  r17, 5
62
WGLOOPA:   ldi  r18, 71
63
WGLOOPB:   dec  r18
64
           brne WGLOOPB
65
       dec  r17
66
           brne WGLOOPA
67
           ret                          ; wieder zurück
68
 
69
delay1600us:                               ; 1,6ms Pause
70
           ldi  r17, 12
71
WGLOOP0:   ldi  r18, 178
72
WGLOOP1:   dec  r18
73
           brne WGLOOP1
74
       dec  r17
75
           brne WGLOOP0
76
           ret                          ; wieder zurück
77
78
delay40ms:                               ; 40ms Pause
79
           ldi  r17, 230
80
WGLOOP0_:   ldi  r18, 250
81
WGLOOP1_:   dec  r18
82
           brne WGLOOP1_
83
       dec  r17
84
           brne WGLOOP0_
85
           ret                          ; wieder zurück
86
 
87
; LCD init EA DOGM163S-A VCC = 5V
88
89
LCD_init:
90
//wait time >40mS after VDD stable
91
           rcall  delay40ms
92
//Function set
93
       ldi r16,0b00000011
94
       out PORTD, r16
95
       rcall LCD_enable
96
//wait time >1,6mS
97
      rcall delay1600us
98
//Function set
99
       rcall LCD_enable  //2x
100
//wait time  >26.3uS
101
      rcall delay26us
102
//Function set
103
       rcall LCD_enable  //3x
104
//wait time  >26.3uS
105
      rcall delay26us
106
//Function set
107
       ldi r16,0b00000010 //4-Bit
108
       out PORTD, r16
109
       rcall LCD_enable
110
//wait time  >26.3uS
111
      rcall delay26us
112
//Function set
113
       ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1
114
       out PORTD, r16
115
       rcall LCD_command
116
//wait time  >26.3uS
117
      ;rcall delay50us
118
//Bias set
119
       ldi r16,0b00011101 //BS: 1/4, 3-zeiliges LCD
120
       out PORTD, r16
121
       rcall LCD_command
122
//wait time >26.3uS
123
      ;rcall delay50us
124
//Contrast Set
125
       ldi r16,0b01111100 //Konstrast C3, C2, C1 setzen
126
       out PORTD, r16
127
       rcall LCD_command
128
//wait time >26.3uS
129
      ;rcall delay50us
130
//Power/ICON/Contrast control
131
       ldi r16,0b01010000 //Booster aus, Kontrast C5, C4 setzen
132
       out PORTD, r16
133
       rcall LCD_command
134
//wait time >26.3uS
135
      ;rcall delay50us
136
//Follower control
137
      ldi r16,0b01101100 //Spannungsfolger und Verstärkung setzen
138
       out PORTD, r16
139
       rcall LCD_command
140
//wait time >26.3uS
141
      ;rcall delay50us
142
//Display ON/OFF control
143
      ldi r16,0b00001111 //Display ein, Cursor ein, Cursor blinken
144
       out PORTD, r16
145
       rcall LCD_command
146
//wait time >26.3uS
147
      ;rcall delay50us      
148
      ret
149
150
LCD_clear:
151
      ldi r16,0b00000001 //Display löschen, Cursor Home
152
      out PORTD, r16
153
      rcall LCD_enable
154
      rcall delay26us      
155
      ret

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von P. S. (Gast)


Lesenswert?

Marcus Scholz schrieb:

> R/W ziehe ich auf GND und Reset auf +5V.

Wie z.B. hier beschrieben: 
Beitrag "DOGM132-5 mit SPI ansteuern" duerfte das Display einen 
ordentlichen Reset fuer die Initialisierung erwarten.

von Flo (Gast)


Lesenswert?

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.

von Marcus S. (msohz)


Angehängte Dateien:

Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>Habe so gerechnet: 4MHz, sind 25nS pro Takt. Dann benötige ich...

Nee. 250ns

MfG Spess

von Marcus S. (msohz)


Lesenswert?

Hi,

na dann sind die delays ja gar nicht zu knapp :)

-LOL- werde dass mal überarbeiten. Danke!

Gruß Marcus

von Marcus S. (msohz)


Lesenswert?

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
49
out PORTD, r17
50
rcall LCD_enable
51
ldi r16,1
52
rcall warte1ms
53
ret
54
55
LCD_enable:
56
sbi PORTD, 5        //enable high
57
nop              //3 Taktzyklen warten
58
nop
59
nop
60
nop
61
nop
62
cbi PORTD, 5        //enable wieder low
63
nop
64
nop
65
nop
66
ret
67
68
69
;Delay Schleifen
70
warte1ms:
71
      push r24
72
      push r25
73
      ldi r24, LOW(TAKT/4000)    ;4MHz ergibt 1000
74
      ldi r25, HIGH(TAKT/4000)  ;1 Takt ist hier 250ns
75
warte1ms_:  sbiw r24,1          ;subtrahiere 1 (2-Takte)
76
      brne warte1ms_        ;2-Takte
77
      nop              ;bis hier (4000 Takte = 1000000 ns)
78
      pop r25
79
      pop r24
80
      ret
81
82
wartex10ms:                ;wartet 10ms * Faktor aus r16
83
      push r16
84
      push r24
85
      push r25
86
wartex10msa:ldi r24, LOW(TAKT/400)  
87
      ldi r25, HIGH(TAKT/400)  
88
wartex10msb:sbiw r24,1          ;subtrahiere 1 (2-Takte)
89
      brne wartex10msb      ;2-Takte
90
      dec r16            ;Zähler vermindern
91
      brne wartex10msa
92
      pop r25
93
      pop r24
94
      pop r16
95
      ret
96
97
 
98
; LCD init EA DOGM163S-A VCC = 5V
99
100
LCD_init:
101
//RESET des ST7036
102
//PORTB0 ist Reset
103
104
    sbi PORTB , 0              ;RESET auf high
105
  
106
    //10ms warten
107
    ldi r16, 1
108
    rcall wartex10ms
109
110
    cbi PORTB , 0              ;RESET auf low
111
112
    //100ms warten
113
    ldi r16, 10
114
    rcall  wartex10ms
115
    
116
    sbi PORTB , 0              ;RESET auf high
117
118
//wait time >40mS after VDD stable
119
    ldi r16, 10
120
        rcall  wartex10ms
121
//Function set
122
       ldi r16,0b00000011
123
       out PORTD, r16
124
       rcall LCD_enable
125
//wait time >1,6mS
126
      rcall wartex10ms
127
//Function set
128
       rcall LCD_enable  //2x
129
//wait time  >26.3uS
130
      rcall warte1ms
131
//Function set
132
       rcall LCD_enable  //3x
133
//wait time  >26.3uS
134
      rcall warte1ms
135
//Function set
136
       ldi r16,0b00000010 //4-Bit
137
       out PORTD, r16
138
       rcall LCD_enable
139
//wait time  >26.3uS
140
      rcall warte1ms
141
//Function set
142
       ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1
143
       out PORTD, r16
144
       rcall LCD_command
145
//wait time  >26.3uS
146
147
//Bias set
148
       ldi r16,0b00011101 //BS: 1/4, 3-zeiliges LCD
149
       out PORTD, r16
150
       rcall LCD_command
151
//wait time >26.3uS
152
153
//Contrast Set
154
       ldi r16,0b01111100 //Konstrast C3, C2, C1 setzen
155
       out PORTD, r16
156
       rcall LCD_command
157
//wait time >26.3uS
158
      
159
//Power/ICON/Contrast control
160
       ldi r16,0b01010000 //Booster aus, Kontrast C5, C4 setzen
161
       out PORTD, r16
162
       rcall LCD_command
163
//wait time >26.3uS
164
      
165
//Follower control
166
      ldi r16,0b01101100 //Spannungsfolger und Verstärkung setzen
167
       out PORTD, r16
168
       rcall LCD_command
169
//wait time >26.3uS
170
      
171
//Display ON/OFF control
172
      ldi r16,0b00001111 //Display ein, Cursor ein, Cursor blinken
173
       out PORTD, r16
174
       rcall LCD_command
175
//wait time >26.3uS
176
      
177
      ret
178
179
LCD_clear:
180
      ldi r16,0b00000001 //Display löschen, Cursor Home
181
      out PORTD, r16
182
      rcall LCD_enable
183
      rcall warte1ms
184
      ret

von P. S. (Gast)


Lesenswert?

Was hast du mit CSB gemacht, fest auf low?

von spess53 (Gast)


Lesenswert?

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

von Marcus S. (msohz)


Lesenswert?

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

von Marcus S. (msohz)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von Marcus S. (msohz)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.