Forum: Mikrocontroller und Digitale Elektronik Zeile 2 eines LC_Display beschreiben


von Steffen K. (steffen3)


Lesenswert?

Hi,
ich habe ein Problem damit die zweite Zeile eines 2*16 LCD zu 
beschreiben.
Da ich von Assembler nichts verstehe, bin ich auf eine Lösung in C 
angewiesen. Die erste Zeile lässt sich einwandfrei benutzen.
Als init()-Funktion für das Display verwende ich die Funkktion die das 
Tutorial "AVR-GCC-Tutorial" beschreibt.
1
void lcd_init(void)
2
{
3
  LCD_DDR=LCD_DDR |0xF0;
4
  LCD_RS_DDR|=(1<<LCD_RS);
5
  LCD_EN_DDR|=(1<<LCD_EN);
6
  _delay_ms(15);
7
  LCD_PORT &=0x0F;
8
  LCD_PORT |= 0x30;
9
  LCD_RS_PORT &= ~(1<<LCD_RS);
10
  lcd_enable();
11
  _delay_ms(5);
12
  lcd_enable();  
13
  _delay_ms(1);
14
  lcd_enable();
15
  _delay_ms(1);
16
17
  LCD_PORT &= 0x0F;
18
  LCD_PORT |=0x20;
19
  lcd_enable();
20
21
  lcd_command(0x28);
22
  lcd_command(0x0C);
23
  lcd_command(0x06);
24
  lcd_clear();
25
}

Musste die Pinbelegung etwas ändern, weil ich sie noch für andere Dinge 
brauche.

Da ich nicht weiter weiß, hoffe ich das mir da jemand weiterhelfen kann.

Gruss Steffen

von Marvin M. (Gast)


Lesenswert?

Den Commands nach ist das ein LCD mit Standard-Controller. Versuchs mal 
mit lcd_command(0xC0).
Müsste auch im Datenblatt des LCD-Controllers nachzulesen sein ;-)
Gleich die Antwort auf die nächste Frage: Die erste Zeile wird mit 0x80 
angesprochen ;-)

von Steffen K. (steffen3)


Lesenswert?

Hallo,
erstmal danke für die schnelle Antwort. Leider funktiniert es nicht, 
wenn ich
1
lcd_command(0xC0)
verwende.

von Otto (Gast)


Lesenswert?

Hallo Steffen,

manche Displays haben zwar nur 16 Zeichen, die 2. Zeile beginnt aber 
nach 40 Zeichen.

Gruss Otto

von Steffen K. (steffen3)


Lesenswert?

ich habe
1
lcd_command(0x29)
 versucht, geht aber auch nicht. Beim Verstellen des Kontrasts ist mir 
aufgefallen, dass ich ihn in der zweiten Zeile nicht verändern kann und 
er konstant ehr schwach ist.
Daher frage ich mich, ob ich die zweite Zeile vielleicht auch 
initialisieren muss?

von Johannes M. (johnny-m)


Lesenswert?

Hat das Display nur einen Enable-Eingang? Es gibt auch Displays, die 
für jede Zeile nen eigenen Controller haben. Die haben dann zwei Enables 
und müssen auch entsprechend angesteuert werden.

von winne (Gast)


Lesenswert?

Am Besten ihr lest mal die Datasheet.

Zum einen gibt es entsprechende Inits die zahl der aktivierten Zeilen 
betreffend.

Zum anderen ist die richtige Adressierung zu beachten sie kann von 
sowohl vom LCD-Controller als vom konkreten Modul abhängen.

Zumeist hat jede Zeile 40-Byte unabhängig von der Anzahl der tatsächlich 
verwendeten Bytes.

von Steffen K. (steffen3)


Lesenswert?

Johannes M. wrote:
> Hat das Display nur einen Enable-Eingang?
Das LCD ist ein Addon von "myavr" und verfügt laut Datenblatt über die 
Eingänge RS=Enable und E=Enable.
Folgender Quelltext beschreibt auch die zweite Zeile, leider habe ich 
von Assembler keine Ahnung und verstehe nicht warum es mit dem Quelltext 
klappt.
1
;---------------------------------------------------------------------------
2
; Title         : Programmbeispiel für myAVR-Board mit LCD Add-On
3
;---------------------------------------------------------------------------
4
; Funktion      : gibt Zeichenketten auf dem myAVR LCD Modul, 2 Zeilen
5
; Schaltung     : PORT D2 = RS, PORT D3 = E, PORT D4-7 = D4-7
6
;---------------------------------------------------------------------------
7
; Prozessor     : ATmega8
8
; Takt      : 3,6864 MHz
9
; Sprache       : Assembler
10
; Datum         : 03.02.2005
11
; Version       : 1.6
12
; Autor         : Dipl. Ing. Päd. Alexander Huwaldt
13
;---------------------------------------------------------------------------
14
.equ  F_CPU,  3686400
15
.include  "AVR.H"
16
;---------------------------------------------------------------------------
17
; Reset- und Interruptvektoren          ; VNr.  Beschreibung
18
  rjmp  main  ; 1     POWER ON RESET
19
  reti    ; 2     Int0-Interrupt
20
  reti    ; 3     Int1-Interrupt
21
  reti    ; 4     TC2 Compare Match
22
  reti    ; 5     TC2 Overflow
23
  reti    ; 6     TC1 Capture
24
  reti    ; 7     TC1 Compare Match A
25
  reti    ; 8     TC1 Compare Match B
26
  reti    ; 9     TC1 Overflow
27
  reti    ; 10    TC0 Overflow
28
  reti    ; 11    SPI, STC Serial Transfer Complete
29
  reti    ; 12    UART Rx Complete
30
  reti    ; 13    UART Data Register Empty
31
  reti    ; 14    UART Tx complete
32
  reti    ; 15    ADC Conversion Complete
33
  reti    ; 16    EEPROM Ready
34
  reti    ; 17    Analog Comperator
35
  reti    ; 18    TWI (I²C) Serial Interface
36
  reti    ; 19    Store Program Memory Ready
37
;---------------------------------------------------------------------------
38
; Start, Power ON, Reset
39
main:  ldi  r16,lo8(RAMEND)
40
  out  SPL,r16  ; Init Stackpointer LO
41
  ldi  r16,hi8(RAMEND)
42
  out  SPH,r16  ; Init Stackpointer HI
43
  rcall  LCD_init
44
  rcall  LCD_clear
45
;---------------------------------------------------------------------------
46
mainloop:  rcall  wait
47
  ldi  r16,'H'
48
  rcall  LCD_data
49
  ldi  r16,'a'
50
  rcall  LCD_data
51
  ldi  r16,'l'
52
  rcall  LCD_data
53
  ldi  r16,'l'
54
  rcall  LCD_data
55
  ldi  r16,'o'
56
  rcall  LCD_data
57
  ldi  r16,' '
58
  rcall  LCD_data
59
60
  rcall  LCD_line2
61
62
  ldi  r16,'S'
63
  rcall  LCD_data
64
  ldi  r16,'i'
65
  rcall  LCD_data
66
  ldi  r16,'S'
67
  rcall  LCD_data
68
  ldi  r16,'y'
69
  rcall  LCD_data
70
  ldi  r16,' '
71
  rcall  LCD_data
72
73
  rcall  LCD_home
74
75
  rjmp  mainloop
76
;===========================================================================
77
; hier Unterprogramme und Interruptroutinen zufügen
78
;---------------------------------------------------------------------------
79
wait:  push  r24
80
  ldi  r24,0x13  ; hier delay einstellen 13 = ca. 20yS
81
w1:  subi  r24,0x01
82
  rcall  wait20ms
83
  brcc  w1
84
  pop  r24
85
  ret
86
;---------------------------------------------------------------------------
87
wait5ms:  ldi  r16,255
88
  ldi  r17,26
89
w5ms:  dec  r16
90
  brne  w5ms
91
  dec  r17
92
  brne  w5ms
93
  ret
94
;---------------------------------------------------------------------------
95
wait20ms:  ldi  r16,255
96
  ldi  r17,104
97
w20ms:  dec  r16
98
  brne  w20ms
99
  dec  r17
100
  brne  w20ms
101
  ret
102
;---------------------------------------------------------------------------
103
LCD_init:  sbi  DDRD,2  ; LCD RS = OUT
104
  sbi  DDRD,3  ; LCD E  = OUT
105
  sbi  DDRD,4  ; LCD D4 = OUT
106
  sbi  DDRD,5  ; LCD D5 = OUT
107
  sbi  DDRD,6  ; LCD D6 = OUT
108
  sbi  DDRD,7  ; LCD D7 = OUT
109
  cbi  PORTD,2  ; LDC RS = Low
110
111
; warte bis PowerUp
112
  ldi  r18,20
113
powerup:  rcall  wait5ms
114
  dec  r18
115
  brne  powerup  ; Power-Up Wartezyklus min 30 ms
116
117
; sende Resetsequenz kompatibel zu HD44780 Industriestandard
118
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 1
119
  out  PORTD,r16
120
  rcall  LCD_enable  ; Enable-Impuls
121
  rcall  wait5ms
122
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 2
123
  out  PORTD,r16
124
  rcall  LCD_enable  ; Enable-Impuls
125
  rcall  wait5ms
126
  ldi  r18,100  ; Wartezyklus bei RESET LCD min 100 µs
127
resetLCD:
128
  nop
129
  nop
130
  nop
131
  dec  r18
132
  brne  resetLCD
133
  ldi  r16,0b00110000  ; Reset-Sequenz Teil 3
134
  out  PORTD,r16
135
  rcall  LCD_enable  ; Enable-Impuls
136
  rcall  wait5ms
137
138
; sende init 1
139
  ldi  r16,0b00100000  ; 4 Bit Modus aktivieren
140
  out  PORTD,r16
141
  rcall  LCD_enable  ; Enable-Impuls
142
  rcall  wait5ms
143
  ldi  r16,0b00101000
144
  rcall  LCD_cmd  ; Function Set 4 Bit, 2 Zeilen, 5x7
145
  rcall  LCD_off
146
  rcall  LCD_clear
147
  ldi  r16,0x06
148
  rcall  LCD_cmd  ; Entry Mode Set, increase+shifted
149
  rcall  LCD_on
150
  ret
151
;---------------------------------------------------------------------------
152
LCD_data:  ldi  r18,0b0000100  ; RS = hi
153
  rjmp  LCD_out
154
;---------------------------------------------------------------------------
155
LCD_cmd:  ldi  r18,0b0000000  ; RS = lo
156
LCD_out:  mov  r17,r16
157
  swap  r17
158
  andi  r16,0b11110000
159
  or  r16,r18
160
  andi  r17,0b11110000
161
  or  r17,r18
162
  out  PORTD,r16
163
  rcall  LCD_enable
164
  out  PORTD,r17
165
  rcall  LCD_enable
166
  rcall  wait5ms
167
  ret
168
;---------------------------------------------------------------------------
169
LCD_enable:  sbi  PORTD,3  ; Enable high
170
  nop    ; kurz warten
171
  nop
172
  nop
173
  cbi  PORTD,3  ; Enable wieder low
174
  ret
175
;---------------------------------------------------------------------------
176
LCD_clear:  ldi  r16,0b00000001  ; Display löschen
177
  rcall  LCD_cmd
178
  rcall  wait5ms
179
  ret
180
;---------------------------------------------------------------------------
181
LCD_off:  ldi  r16,0b00001000
182
  rcall  LCD_cmd
183
  rcall  wait5ms
184
  ret
185
;---------------------------------------------------------------------------
186
LCD_on:  ldi  r16,0x0E
187
  rcall  LCD_cmd
188
  rcall  wait5ms
189
  ret
190
;---------------------------------------------------------------------------
191
LCD_home:  ldi  r16,0b00000010  ; Display Cursor HOME
192
  rcall  LCD_cmd
193
  rcall  wait5ms
194
  ret
195
;---------------------------------------------------------------------------
196
LCD_line1:  ldi  r16,0b10000000  ; DRAM auf Adresse 0x00
197
  rcall  LCD_cmd
198
  rcall  wait5ms
199
  ret
200
;---------------------------------------------------------------------------
201
LCD_line2:  ldi  r16,0b11000000  ; DRAM auf Adresse 0x40
202
  rcall  LCD_cmd
203
  rcall  wait5ms
204
  ret
205
;---------------------------------------------------------------------------
206
; Goto r16 = Adresse (Zeile 1 = 0x00..0x0F, Zeile 2 = 0x40..0x4F)
207
LCD_goto:  ori  r16,0b10000000  ; Goto DRAM auf Adresse r16
208
  rcall  LCD_cmd
209
  rcall  wait5ms
210
  ret
211
;---------------------------------------------------------------------------

Der Code ist eine Codevorlage aus dem Programm "myAVR Workpad", hoffe 
das ich ihn hier posten darf.

von Marvin M. (Gast)


Lesenswert?

"Beim Verstellen des Kontrasts ist mir
aufgefallen, dass ich ihn in der zweiten Zeile nicht verändern kann und
er konstant ehr schwach ist."

Dann stimmt etwas mit der Initialisierung des LCD nicht. Poste mal 
Deinen kompletten C-Code (idealerweise als *.zip angehängt).
Im Prinzip ist der Befehl 0x28 für die Initialisierung zuständig, den 
hast Du in Deinem ersten Code-Fragment drinnen. Könnte ein 
Timing-Problem sein. Ganz schlau werde ich auch nicht daraus, dass Du 
zuerst den LCD-Port "von Hand" durchklingelst und später dann doch eine 
Funktion "lcd_command()" verwendest.

von Marvin M. (Gast)


Lesenswert?

Ah- ist schon spät... habs gerade bemerkt, 4-Bit Modus... klar.

Aber Du solltest den Code besser mit Copy & Paste einfügen ;-)

Wie schon vermutet, ist Deine Initialisierungsroutine falsch. In zwei 
Zeilen hast Du Zahlendreher drinnen:
1
void lcd_init(void)
2
{
3
  LCD_DDR=LCD_DDR |0xF0;
4
  LCD_RS_DDR|=(1<<LCD_RS);
5
  LCD_EN_DDR|=(1<<LCD_EN);
6
  _delay_ms(15);
7
  LCD_PORT &=0x0F;
8
  
9
  // falsch: LCD_PORT |= 0x30; !!!
10
  LCD_PORT |= 0x03;  // richtig...
11
12
  LCD_RS_PORT &= ~(1<<LCD_RS);
13
  lcd_enable();
14
  _delay_ms(5);
15
  lcd_enable();  
16
  _delay_ms(1);
17
  lcd_enable();
18
  _delay_ms(1);
19
20
  LCD_PORT &= 0x0F;
21
  // falsch: LCD_PORT |=0x20; !!!
22
  LCD_PORT |=0x02;  // richtig...
23
24
  lcd_enable();
25
26
  lcd_command(0x28);
27
  lcd_command(0x0C);
28
  lcd_command(0x06);
29
  lcd_clear();
30
}

von Steffen K. (steffen3)


Angehängte Dateien:

Lesenswert?

Das ändern der init() hat nichts gebracht, im Anhang ist der komplette 
Quelltext.

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.