Forum: Mikrocontroller und Digitale Elektronik LCD-Modul TC1602E-01


von Pierre G. (bqube)


Lesenswert?

Guten tag alle miteinander

Und zwar habe ich das oben beschriebene LCD Display welches aber nix 
anzeigt ausser
In der ersten Zeile schwarze kästchen.. angeschlossen habe ich dieses 
wie folgt

Portd 0-3 an Db 4-7  portd 4 an Rs  portd 5 an E

Das Programm ist das selbe wie im Assembler Beispiel und ich benutze den
Internen 4 MHz

Funktioniert dieses Display überhaupt im 4bit Modus

Mfg Bqube

von Oliver J. (skriptkiddy)


Lesenswert?

Pierre Gnauck schrieb:
> Funktioniert dieses Display überhaupt im 4bit Modus
Ja das tut es.

Gruß Oliver

von Uwe (de0508)


Lesenswert?

Pierre Gnauck schrieb:
> Portd 0-3 an Db 4-7  portd 4 an Rs  portd 5 an E

Guten Morgen,

und das R/#W Pin vom LCD?

von Pierre G. (bqube)


Lesenswert?

Den R/W pin vom Display habe ich auf Masse gelegt für Schreiben..

Mfg Bqube

von Pierre G. (bqube)


Lesenswert?

Das Programm was ich verwende ist das hier
1
.include "m8def.inc"
2
 
3
; .def definiert ein Synonym (Namen) für ein µC Register
4
.def temp1 = r16
5
.def temp2 = r17
6
.def temp3 = r18
7
 
8
           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
9
           out SPL, temp1
10
           ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
11
           out SPH, temp1
12
 
13
           ldi temp1, 0xFF    ; Port D = Ausgang
14
           out DDRD, temp1
15
 
16
           rcall lcd_init     ; Display initialisieren
17
           rcall lcd_clear    ; Display löschen
18
 
19
           ldi temp1, 'T'     ; Zeichen anzeigen
20
           rcall lcd_data
21
 
22
           ldi temp1, 'e'     ; Zeichen anzeigen
23
           rcall lcd_data
24
           
25
           ldi temp1, 's'     ; Zeichen anzeigen
26
           rcall lcd_data
27
 
28
           ldi temp1, 't'     ; Zeichen anzeigen
29
           rcall lcd_data
30
 
31
loop:
32
           rjmp loop
33
34
35
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
36
;;                 LCD-Routinen                ;;
37
;;                 ============                ;;
38
;;              (c)andreas-s@web.de            ;;
39
;;                                             ;;
40
;; 4bit-Interface                              ;;
41
;; DB4-DB7:       PD0-PD3                      ;;
42
;; RS:            PD4                          ;;
43
;; E:             PD5                          ;;
44
;;                                             ;;
45
;; Takt:          4 MHz                        ;;
46
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47
 
48
 
49
 
50
 ;sendet ein Datenbyte an das LCD
51
lcd_data:
52
           mov temp2, temp1             ; "Sicherungskopie" für
53
                                        ; die Übertragung des 2.Nibbles
54
           swap temp1                   ; Vertauschen
55
           andi temp1, 0b00001111       ; oberes Nibble auf Null setzen
56
           sbr temp1, 1<<4              ; entspricht 0b00010000 (Anm.1)
57
           out PORTD, temp1             ; ausgeben
58
           rcall lcd_enable             ; Enable-Routine aufrufen
59
                                        ; 2. Nibble, kein swap da es schon
60
                                        ; an der richtigen stelle ist
61
           andi temp2, 0b00001111       ; obere Hälfte auf Null setzen 
62
           sbr temp2, 1<<4              ; entspricht 0b00010000
63
           out PORTD, temp2             ; ausgeben
64
           rcall lcd_enable             ; Enable-Routine aufrufen
65
           rcall delay50us              ; Delay-Routine aufrufen
66
           ret                          ; zurück zum Hauptprogramm
67
 
68
 ; sendet einen Befehl an das LCD
69
lcd_command:                            ; wie lcd_data, nur RS=0
70
           mov temp2, temp1
71
           swap temp1
72
           andi temp1, 0b00001111
73
           out PORTD, temp1
74
           rcall lcd_enable
75
           andi temp2, 0b00001111
76
           out PORTD, temp2
77
           rcall lcd_enable
78
           rcall delay50us
79
           ret
80
 
81
 ; erzeugt den Enable-Puls
82
 ;
83
 ; Bei höherem Takt (>= 8 MHz) kann es notwendig sein, 
84
 ; vor dem Enable High 1-2 Wartetakte (nop) einzufügen. 
85
 ; Siehe dazu http://www.mikrocontroller.net/topic/81974#685882
86
lcd_enable:
87
           sbi PORTD, 5                 ; Enable high
88
           nop                          ; mindestens 3 Taktzyklen warten
89
           nop
90
           nop
91
           cbi PORTD, 5                 ; Enable wieder low
92
           ret                          ; Und wieder zurück                     
93
 
94
 ; Pause nach jeder Übertragung
95
delay50us:                              ; 50µs Pause (bei 4 MHz)
96
           ldi  temp1, $42
97
delay50us_:dec  temp1
98
           brne delay50us_
99
           ret                          ; wieder zurück
100
 
101
 ; Längere Pause für manche Befehle
102
delay5ms:                               ; 5ms Pause (bei 4 MHz)
103
           ldi  temp1, $21
104
WGLOOP0:   ldi  temp2, $C9
105
WGLOOP1:   dec  temp2
106
           brne WGLOOP1
107
           dec  temp1
108
           brne WGLOOP0
109
           ret                          ; wieder zurück
110
 
111
 ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
112
lcd_init:
113
           ldi  temp3,50
114
powerupwait:
115
           rcall  delay5ms
116
           dec  temp3
117
           brne powerupwait
118
           ldi temp1, 0b00000011        ; muss 3mal hintereinander gesendet
119
           out PORTD, temp1             ; werden zur Initialisierung
120
           rcall lcd_enable             ; 1
121
           rcall delay5ms
122
           rcall lcd_enable             ; 2
123
           rcall delay5ms
124
           rcall lcd_enable             ; und 3!
125
           rcall delay5ms
126
           ldi temp1, 0b00000010        ; 4bit-Modus einstellen
127
           out PORTD, temp1
128
           rcall lcd_enable
129
           rcall delay5ms
130
           ldi temp1, 0b00101000        ; 4Bit / 2 Zeilen / 5x8
131
           rcall lcd_command
132
           ldi temp1, 0b00001100        ; Display ein / Cursor aus / kein Blinken
133
           rcall lcd_command
134
           ldi temp1, 0b00000100        ; inkrement / kein Scrollen
135
           rcall lcd_command
136
           ret
137
 
138
 ; Sendet den Befehl zur Löschung des Displays
139
lcd_clear:
140
           ldi temp1, 0b00000001   ; Display löschen
141
           rcall lcd_command
142
           rcall delay5ms
143
           ret
144
 
145
 ; Sendet den Befehl: Cursor Home
146
lcd_home:
147
           ldi temp1, 0b00000010   ; Cursor Home
148
           rcall lcd_command
149
           rcall delay5ms
150
           ret

Wie oben beschrieben benutze ich den internen Quarz auf 4Mhz

von Pierre G. (bqube)


Lesenswert?

So ich hab nun das Program auf 8Bit umgestellt .... wurde auch im AVR 
Simulator von oshonsoft ohne Probleme ausgegeben ... aber könnt ihr da 
bitte mal drüber schauen ob das so auch auf der Hardware laufen würde ?
danke schonmal

Mfg Bqube
1
.include "m8def.inc"
2
 
3
;PORTB5 = E
4
;PORTB4 = RS
5
;PORTB3 = RW
6
;PORTD 0-7 Datenleitungen
7
8
9
10
 
11
           ldi R16, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
12
           out SPL, R16
13
           ldi R16, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
14
           out SPH, R16
15
 
16
ldi R21, 0xFF    ; Port D = Ausgang
17
out DDRD, R21
18
19
ldi R21, 0xFF    ; Port B = Ausgang
20
out DDRB, R21
21
22
 
23
           rcall lcd_init     ; Display initialisieren
24
           rcall LCDCLS    ; Display löschen
25
 
26
           ldi R20, 'T'     ; Zeichen anzeigen
27
           rcall LCDDATA
28
       
29
 
30
           ldi R20, 'e'     ; Zeichen anzeigen
31
           rcall LCDDATA
32
           
33
           ldi R20, 's'     ; Zeichen anzeigen
34
           rcall LCDDATA
35
 
36
           ldi R20, 't'     ; Zeichen anzeigen
37
           rcall LCDDATA
38
 
39
loop:
40
           rjmp loop
41
42
43
44
45
lcd_init: ;8Bit MODUS
46
rcall WARTENG
47
 LDI R20,0b00110000
48
 OUT PORTD,R20
49
rcall LCDOP
50
rcall WARTENK
51
rcall LCDOP
52
rcall WARTENK
53
rcall LCDOP
54
rcall WARTENK
55
rcall LCDOP
56
rcall WARTENK
57
 LDI R20,0b00111000  ;2 ZEILEN
58
 OUT PORTD,R20
59
rcall LCDOP
60
rcall WARTENK
61
 LDI R20,0b00001000  ;LCD AUS
62
 OUT PORTD,R20
63
rcall LCDOP
64
rcall WARTENK
65
 LDI R20,0b00000001  ;LCD LÖSCHEN
66
 OUT PORTD,R20
67
rcall LCDOP
68
rcall WARTENK
69
 LDI R20,0b00000110 ;Kursor nach rechts wandernd, kein Display shift
70
 OUT PORTD,R20
71
rcall LCDOP
72
rcall WARTENK
73
 LDI R20,0b00001100  ;LCD EIN
74
 OUT PORTD,R20
75
rcall LCDOP
76
rcall WARTENK
77
LDI R20,0b00000000
78
OUT PORTD,R20
79
ret
80
81
LCDDATA:
82
OUT PORTD,R20
83
 SBI PORTB,4
84
 CBI PORTB,3
85
  NOP
86
 NOP
87
  SBI PORTB,5
88
 NOP
89
 NOP
90
 NOP
91
 NOP
92
  CBI PORTB,5
93
 NOP
94
 NOP
95
LDI R20,0b00000000
96
OUT PORTD,R20
97
rcall WARTENK
98
ret
99
100
LCDOP:    ;SENDEN DER EINSTELLUNGEN
101
  CBI PORTB,4
102
  CBI PORTB,3
103
 NOP
104
 NOP
105
  SBI PORTB,5
106
 NOP
107
 NOP
108
 NOP
109
 NOP
110
  CBI PORTB,5
111
 NOP
112
 NOP
113
ret
114
115
LCDCLS:  ;LCD LÖSCHEN
116
 LDI R20,0b00000001
117
 OUT PORTD,R20
118
rcall LCDOP
119
rcall WARTENK
120
LDI R20,0b00000000
121
OUT PORTD,R20
122
ret
123
124
LCDHOME:
125
 LDI R20,0b00000010
126
 OUT PORTD,R20
127
rcall LCDOP
128
rcall WARTENK
129
LDI R20,0b00000000
130
OUT PORTD,R20
131
ret
132
133
134
135
WARTENK:    ;5ms SCHLEIFE
136
137
          ldi  R17, 0x06
138
WGLOOP0:  ldi  R18, 0x37
139
WGLOOP1:  ldi  R19, 0xC9
140
WGLOOP2:  dec  R19
141
          brne WGLOOP2
142
          dec  R18
143
          brne WGLOOP1
144
          dec  R17
145
          brne WGLOOP0
146
          nop
147
          nop
148
ret
149
150
WARTENG:    ;20ms SCLHLEIFE
151
152
WGLOOP11:  ldi  R19, 0x79
153
WGLOOP22:  dec  R19
154
          brne WGLOOP22
155
          dec  R18
156
          brne WGLOOP11
157
          dec  R17
158
          brne WGLOOP0
159
          ldi  R17, 0x01
160
WGLOOP33:  dec  R17
161
          brne WGLOOP33
162
          nop
163
          nop
164
ret

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Den 8-Bit Modus benutze ich nicht, weil der mir zu viele Portpins 
wegfuttert. Aber bei deinem 4-bit Programm ist vermutlich der Fehler, 
das du den ganzen Port beschreibst und damit auch die Kontrollleitungen 
unabsichtlich verwurschtelst:

Pierre Gnauck schrieb:
> ldi temp1, 0b00000011        ; muss 3mal hintereinander gesendet
>   out PORTD, temp1             ; werden zur Initialisierung

Warum eigentlich das Rad immer neu erfinden? Da gibt es tonnenweise 
Beispiele - selbst in Assembler. Ich würde dir auch empfehlen, Portpins 
und Ports in Definitionen zu packen, damit du die Routinen auch mal in 
einer anderen Hardware Konfiguration benutzen kannst. z.B.:
1
.equ   LCD_RS_PORT    PORTD
2
.equ   LCD_RS_PIN     4
3
; und dann kannst du schreiben
4
    sbi   LCD_RS_PORT,LCD_RS_PIN     ; RS Pin high

Gehe also schrittweise vor: Fang an mit einer Routine, die ein Nibble 
(Halbbyte) aufs LCD schreibt. Brauchst du zur Initialisierung eh. Mach 
eine Routine die unter Benutzung der ersten ein Kommando Byte schreibt. 
Mach eine Routine, die ein Datenbyte schreibt, usw.

von Pierre G. (bqube)


Lesenswert?

Danke für die hilfe ich überarbeite dann mal meinen 4bit code....

Warum ich das Rad neu erfinde einfach nur damit ich genau versteh wie 
alles funtioniert das init , die daten auf das Display zu bekommen... 
ich will nicht nur kopieren und einfügen sonder verstehn..  :)


Mfg Bqube

von Pierre G. (bqube)


Lesenswert?

So da bin ich wieder also im 8Bit modus hat alles funktioniert aber mit 
dem 4bit Modus komm ich nicht zu recht .....

Ich schicke drei mal diesen wert 0000-0011
dann schicke ich für den 4Bit Modus 0000-0011

So ab jetzt müsste ich alles im 4Bit modus senden seh ich das richtig so 
???

Also muss ich wenn ich z.b 2 Zeilen 5*8 Punkte einstellen will also
0010-1000 Muss ich das Obere Nibble zu erst senden .... da ich vom PORTD 
die Ports 3 2 1 0 verwende müsste ich meinen 8Bit wert vertauschen mit 
swap

dann wird doch aus 0010-1000 = 1000-0010  und dann schicke ich
die ersten 4Bit 1000 und dann die letzten 0010 oder seh ich das falsch 
??

Mfg Bqube

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ja, erst wird das obere Nibble auf die 4 Datenleitungen gelegt (aber 
ohne die anderen Portpins zu ändern!), E auf high und wieder auf low, 
dann das untere Nibble ( und wieder E high->low). Während der ganzen 
Operation müssen RS und RW low sein und da auch bleiben, da es Kommandos 
sind.
Zum Daten schreiben dann wie oben, aber mit RS high.

von Pierre G. (bqube)


Lesenswert?

Ist zwar nich schön aber schau es dir mal bitte an ich finde den fehler 
nicht warum das Display den 4Bit modus nicht will...

danke schonmal


Mfg Bqube

1
.include "m8def.inc"
2
3
;-------------------------I
4
; Port D (7654:3210:)     I
5
; Db LCD     (:7654:3210) I
6
;                         I
7
; PORTD 0 = DB4           I
8
; PORTD 1 = DB5           I
9
; PORTD 2 = DB6           I
10
; PORTD 3 = DB7           I
11
;                         I
12
; PORTB 5 = E             I
13
; PORTB 4 = RS            I
14
; PORTB 3 = RW            I
15
;                         I
16
;-------------------------I
17
18
LDI R16,0xFF
19
OUT DDRB,R16
20
OUT DDRD,R16
21
LDI R16,0x00
22
23
ldi R16, LOW(RAMEND)
24
out SPL, R16
25
ldi R16, HIGH(RAMEND)
26
out SPH, R16
27
28
rcall lcd_load
29
30
ldi r17,'T'
31
rcall daten_4bit_routine
32
33
ldi r17,'E'
34
rcall daten_4bit_routine
35
36
ldi r17,'S'
37
rcall daten_4bit_routine
38
39
ldi r17,'t'
40
rcall daten_4bit_routine
41
42
a:
43
rjmp a
44
45
46
47
48
49
50
pause20:
51
WGLOOP11:
52
ldi  R19, 0x79
53
WGLOOP22:
54
dec  R19
55
brne WGLOOP22
56
dec  R18
57
brne WGLOOP11
58
dec  R17
59
brne WGLOOP0
60
ldi  R17, 0x01
61
WGLOOP33:
62
dec  R17
63
brne WGLOOP33
64
nop
65
nop
66
ret
67
68
pause5:
69
ldi  R17, 0x06
70
WGLOOP0:
71
ldi  R18, 0x37
72
WGLOOP1:
73
ldi  R19, 0xC9
74
WGLOOP2:
75
dec  R19
76
brne WGLOOP2
77
dec  R18
78
brne WGLOOP1
79
dec  R17
80
brne WGLOOP0
81
nop
82
nop
83
ret
84
85
86
daten_4bit_routine:
87
swap r17
88
out portd,r17
89
rcall daten_routine
90
rcall pause5
91
swap r17
92
out portd,r17
93
rcall daten_routine
94
rcall pause5
95
ret
96
97
adress_4bit_routine:
98
swap r17
99
out portd,r17
100
rcall adress_routine
101
rcall pause5
102
swap r17
103
out portd,r17
104
rcall adress_routine
105
rcall pause5
106
ret
107
108
daten_routine:
109
cbi portb,3
110
sbi portb,4
111
nop
112
nop
113
nop
114
sbi portb,5
115
nop
116
nop
117
nop
118
nop
119
nop
120
nop
121
cbi portb,5
122
nop
123
nop
124
nop
125
ret
126
127
adress_routine:
128
cbi portb,3
129
cbi portb,4
130
nop
131
nop
132
nop
133
sbi portb,5
134
nop
135
nop
136
nop
137
nop
138
nop
139
nop
140
cbi portb,5
141
nop
142
nop
143
nop
144
ret
145
146
lcd_load:
147
rcall pause20
148
LDI r17,0b00000011
149
out Portd,r17
150
rcall adress_routine
151
rcall pause5
152
rcall adress_routine
153
rcall pause5
154
rcall adress_routine
155
rcall pause5
156
ldi r17,0b00000010
157
out portd,r17
158
rcall adress_routine
159
rcall pause5
160
ldi r17,0b00101000
161
adress_4bit_routine
162
ldi r17,0b00001000
163
adress_4bit_routine
164
ldi r17,0b00000001
165
adress_4bit_routine
166
ldi r17,0b00000110
167
adress_4bit_routine
168
ldi r17,0b00001100
169
adress_4bit_routine
170
ret

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Das sieht nicht nur nicht schön aus, sondern sogar so, das ich keine 
Lust habe, mich da durchzuwühlen.

Pierre Gnauck schrieb:
> rcall pause20
> LDI r17,0b00000011
> out Portd,r17
> rcall adress_routine
> rcall pause5
> rcall adress_routine
> rcall pause5
> rcall adress_routine
> rcall pause5

Klar ist aber schon mal, das du nach dem ersten Setzen lange warten 
musst, min. 4,1 mS . Lies mal bitte das Datenblatt des KS0066 oder 
HD44780. Bild 24 im Original Hitachi Datenblatt. Und bitte, lies auch 
mal, wie es die andeen machen. Ausserdem zermanschst du immer noch die 
obere Hälfte von PortD mit deinen outs.

von Pierre G. (bqube)


Lesenswert?

Gut werd ich mir mal anschauen ich hab auch schon gedacht es könnte am 
timing liegen aber in den anderen Beiträgen liest man immer nur von er 
muss minimal so und so lang warten dann kann es doch nicht schlimm sein 
wenn der LCD uc was länger wartet oder etwa doch ?..

Mfg Bqube

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

So hab nun den Fehler gefunden es klappt auf jeden fall schonmal im 
Simulator mit dem 4Bit Modus :)

Danke für Hilfe

Mfg Bqube

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Denke dran, der Simulator läuft im Moment mit 4MHz. Wenn dein realer 
Mega auch auf 4MHz gefused ist, kein Problem, bei 8 MHz sind alle 
Warteschleifen natürlich nur halb so lang. Übrigens ist nur der 
originale HD44780 so eine richtige Schnarchnase, die neueren Klone, wie 
z.B. der KS0066 sind da schon schneller.
Hier als kleines Präsent noch eine sehr universelle Warteroutine, im 
Orignal von Steve Wozniak aus dem Apple II ROM. Ein kleines Meisterwerk 
und ermöglicht einen weiten Bereich von Delays:
1
.def  del  = r20  ; delay counter
2
.equ  MS10  = 0x34          ; 10 mSecs
3
.equ  MS30  = 0x60          ; 30 mSecs
4
.equ  MS100  = 0x72    ; roughly 100mS with wozwait @ 8Mhz
5
.equ  second  = 0xe6    ; roughly a second with wozwait @ 8Mhz
6
; steve wozniak's wait routine - this time for AVR 
7
; this is the  routine with del^2 
8
; this wait routine is ingenious and handles wide ranges of delay 
9
; as a hommage to steve i port it to all my embedded systems. 
10
; some presets
11
w1sec:  ldi     del,second
12
        rjmp    wozwait
13
w10ms:  ldi  del,MS10
14
        rjmp  wozwait
15
w30ms:  ldi  del,MS30
16
        rjmp  wozwait
17
w100ms:  ldi  del,MS100
18
;
19
wozwait: push  del
20
wwait2:  push  del
21
wwait1:  subi  del,1  
22
         brne  wwait1
23
         pop  del
24
         subi  del,1
25
         brne  wwait2
26
         pop  del
27
         subi  del,1
28
         brne  wozwait
29
         ret
Im Simulator kannst du auch noch andere Werte für del(r20) ausprobieren 
um dir jede beliebige Verzögerung zu basteln.

von Pierre G. (bqube)


Lesenswert?

Also müssen meine Wartezeiten bei den neueren nich al zu lang sein wie 
bei dem HD44780 .... mein Problem war das ich zwischen den Nibble eine 
pause von 5ms drinn hatte

adress_4bit_routine:
swap r17
out portd,r17
rcall adress_routine
rcall pause5          <-------------    Die hier
swap r17
out portd,r17
rcall adress_routine
rcall pause5
ret

und aus diesem grun hat das ganze nich funtioniert weil der HD44780 nach 
dem ersten Nibble zu lange warten musste ... deswegen hat er diesen nich 
angenommen .....

Ich schreib grad an einer routine die mit hilfe von sbi und cbi die 
Port's setz und löscht so das ich die anderen 4Bit von dem Port nicht 
mit belege.

Mfg Bqube

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.