Forum: Mikrocontroller und Digitale Elektronik kann LCD Datei nicht compilieren


von Fritz B. (kleinfritzchen)


Lesenswert?

Hallo, ich hab eine Datei zum betreiben eines LCD#s an einer 4 Bit 
leitung gefunden und wollte damit etwas experimentieren. Beim 
compilieren gab es aber folgende Fehlermeldung:
Error  1  Illegal use of undefined or forward referenced symbol 
'LCDS_DDR' in conditional  C:\Users\Fritz\Documents\Atmel 
Studio\6.1\LCDTEST4\LCDTEST4\lcd4inc.asm  72  0  LCDTEST4

was ich hier als Anfänger nicht verstehe ist wozu diese .if Anweisung 
überheupt darin vorkommt und ob sie nicht eigentlich überflüssig ist 
weil  doch LCDS_DDR und LCD_DDR immer beide das gleiche Byte zugreifen.
Mein Atmel Studio 6.1 kennt das anscheinend nicht.
Was kann ich tun um diese Meldung zu verhindern?

MfG Fritz

und hier der Code :
1
;*******************************************************************************
2
;  File:  m8_LCD_4bit.asm
3
;      Title:  ATmega8 driver for LCD in 4-bit mode (HD44780)
4
;  Assembler:  AVR assembler/AVR Studio
5
;    Version:  1.0
6
;    Created:  April 5th, 2004
7
;     Target:  ATmega8
8
; Christoph Redecker, http://www.avrbeginners.net 
9
; BellaD ,www.bellibot.com - some encantements
10
; change to include file lcd4inc.asm
11
;*******************************************************************************
12
13
; Some notes on the hardware:
14
;ATmega8 (clock frequency doesn't matter, tested with 1 MHz to 8 MHz)
15
; PortD.1 -> LCD RS (register select)
16
; PortD.2 -> LCD RW (read/write)
17
; PortD.3 -> LCd E (Enable)
18
; PortD.4 ... PortD.7 -> LCD data.4 ... data.7
19
; the other LCd data lines can be left open or tied to ground.
20
; the pin Vo can fit to GND for maximum of contrast 
21
22
23
;********* you want this in the main file **********
24
;.equ   LCD_PORT = PORTD
25
;.equ   LCD_DDR  = DDRD
26
;.equ  LCDS_PORT = PORTD
27
;.equ  LCDS_DDR  = DDRD
28
29
;.equ  LCD_RS  = 1
30
;.equ  LCD_RW  = 2
31
;.equ  LCD_E  = 3
32
33
34
;.def  temp  = r16
35
;.def  arg    = r17    ;argument for calling subroutines
36
;.def  arg2  = r18    ;argument for mathematics
37
;.def  return  = r19    ;return value from subroutines
38
39
;***********************************************************************************
40
; the following source is from AVRbeginners.net .great work- well documented
41
; the advantage of read the busyflag in 4-bit mode is, no delay's needed
42
;***********************************************************************************
43
LCD_command8:  ;used for init (we need some 8-bit commands to switch to 4-bit mode!)
44
  in  temp, LCD_DDR    ;we need to set the high nibble of DDRD while leaving
45
          ;the other bits untouched. Using temp for that.
46
  sbr  temp, 0b11110000  ;set high nibble in temp
47
  out  LCD_DDR, temp    ;write value to DDRD again
48
  in  temp, LCD_PORT    ;then get the port value
49
  cbr  temp, 0b11110000  ;and clear the data bits
50
  cbr  arg, 0b00001111  ;then clear the low nibble of the arg
51
          ;so that no control line bits are overwritten
52
  or  temp, arg    ;then set the data bits (from the arg) in the
53
          ;Port value
54
  out  LCD_PORT, temp    ;and write the port value.
55
  sbi  LCDS_PORT, LCD_E    ;now strobe E
56
  nop
57
  nop
58
  nop
59
  cbi  LCDS_PORT, LCD_E
60
  in  temp, LCD_DDR    ;get DDRD to make the data lines input again
61
  cbr  temp, 0b11110000  ;clear data line direction bits
62
  out  LCD_DDR, temp    ;and write to DDRD
63
  ret
64
65
LCD_putchar:
66
  push  arg    ;save the argmuent (it's destroyed in between)
67
  in  temp, LCD_DDR    ;get data direction bits
68
  sbr  temp, 0b11110000  ;set the data lines to output
69
  out  LCD_DDR, temp    ;write value to DDRD
70
  in  temp, LCD_PORT    ;then get the data from PortD
71
  
72
.if LCDS_DDR == LCD_DDR    ;if the same port
73
  cbr  temp, 0b11111110  ;clear ALL LCD lines (data and control!)
74
.else
75
  cbr  temp, 0b11110000
76
.endif
77
  
78
  ;cbr  temp, 0b11111110  ;clear ALL LCD lines (data and control!)
79
  
80
  cbr  arg, 0b00001111  ;we have to write the high nibble of our arg first
81
          ;so mask off the low nibble
82
  or  temp, arg    ;now set the arg bits in the Port value
83
  out  LCD_PORT, temp    ;and write the port value
84
  sbi  LCDS_PORT, LCD_RS    ;now take RS high for LCD char data register access
85
  sbi  LCDS_PORT, LCD_E    ;strobe Enable
86
  nop
87
  nop
88
  nop
89
  cbi  LCDS_PORT, LCD_E
90
  pop  arg    ;restore the arg, we need the low nibble now...
91
  cbr  temp, 0b11110000  ;clear the data bits of our port value
92
  swap  arg    ;we want to write the LOW nibble of the argument to
93
          ;the LCD data lines, which are the HIGH port nibble!
94
  cbr  arg, 0b00001111  ;clear unused bits in argument
95
  or  temp, arg    ;and set the required argument bits in the port value
96
  out  LCD_PORT, temp    ;write data to port
97
  sbi  LCDS_PORT, LCD_RS    ;again, set RS
98
  sbi  LCDS_PORT, LCD_E    ;strobe Enable
99
  nop
100
  nop
101
  nop
102
  cbi  LCDS_PORT, LCD_E
103
  cbi  LCDS_PORT, LCD_RS
104
  in  temp, LCD_DDR
105
  cbr  temp, 0b11110000  ;data lines are input again
106
  out  LCD_DDR, temp
107
    ret
108
109
LCD_command:  ;same as LCD_putchar, but with RS low!
110
  push  arg
111
  in  temp, LCD_DDR
112
  sbr  temp, 0b11110000
113
  out  LCD_DDR, temp
114
  in  temp, LCD_PORT
115
  ;cbr  temp, 0b11111110
116
.if LCDS_DDR == LCD_DDR    ;if the same port then
117
  cbr  temp, 0b11111110  ;clear ALL LCD lines (data and control!)
118
.else
119
  cbr  temp, 0b11110000
120
.endif
121
  cbr  arg, 0b00001111
122
  or  temp, arg
123
124
  out  LCD_PORT, temp
125
  sbi  LCDS_PORT, LCD_E
126
  nop
127
  nop
128
  nop
129
  cbi  LCDS_PORT, LCD_E
130
  pop  arg
131
  cbr  temp, 0b11110000
132
  swap  arg
133
  cbr  arg, 0b00001111
134
  or  temp, arg
135
  out  LCD_PORT, temp
136
  sbi  LCDS_PORT, LCD_E
137
  nop
138
  nop
139
  nop
140
  cbi  LCDS_PORT, LCD_E
141
  in  temp, LCD_DDR
142
  cbr  temp, 0b11110000
143
  out  LCD_DDR, temp
144
  ret
145
146
LCD_getchar:
147
  in  temp, LCD_DDR    ;make sure the data lines are inputs
148
  andi  temp, 0b00001111  ;so clear their DDR bits
149
  out  LCD_DDR, temp
150
  sbi  LCDS_PORT, LCD_RS    ;we want to access the char data register, so RS high
151
  sbi  LCDS_PORT, LCD_RW    ;we also want to read from the LCD -> RW high
152
  sbi  LCDS_PORT, LCD_E    ;while E is high
153
  nop
154
  in  temp, PinD    ;we need to fetch the HIGH nibble
155
  andi  temp, 0b11110000  ;mask off the control line data
156
  mov  return, temp    ;and copy the HIGH nibble to return
157
  cbi  LCDS_PORT, LCD_E    ;now take E low again
158
  nop        ;wait a bit before strobing E again
159
  nop  
160
  sbi  LCDS_PORT, LCD_E    ;same as above, now we're reading the low nibble
161
  nop
162
  in  temp, PinD    ;get the data
163
  andi  temp, 0b11110000  ;and again mask off the control line bits
164
  swap  temp      ;temp HIGH nibble contains data LOW nibble! so swap
165
  or  return, temp    ;and combine with previously read high nibble
166
  cbi  LCDS_PORT, LCD_E    ;take all control lines low again
167
  cbi  LCDS_PORT, LCD_RS
168
  cbi  LCDS_PORT, LCD_RW
169
  ret          ;the character read from the LCD is now in return
170
171
LCD_getaddr:  ;works just like LCD_getchar, but with RS low, return.7 is the busy flag
172
  in  temp, LCD_DDR
173
  andi  temp, 0b00001111
174
  out  LCD_DDR, temp
175
  cbi  LCDS_PORT, LCD_RS
176
  sbi  LCDS_PORT, LCD_RW
177
  sbi  LCDS_PORT, LCD_E
178
  nop
179
  in  temp, PinD
180
  andi  temp, 0b11110000
181
  mov  return, temp
182
  cbi  LCDS_PORT, LCD_E
183
  nop
184
  nop
185
  sbi  LCDS_PORT, LCD_E
186
  nop
187
  in  temp, PinD
188
  andi  temp, 0b11110000
189
  swap  temp
190
  or  return, temp
191
  cbi  LCDS_PORT, LCD_E
192
  cbi  LCDS_PORT, LCD_RW
193
  ret
194
195
LCD_wait:        ;read address and busy flag until busy flag cleared
196
  
197
  rcall  LCD_getaddr
198
  andi  return, 0x80
199
  brne  LCD_wait
200
  ret
201
202
203
LCD_delay:
204
  clr  r2
205
  LCD_delay_outer:
206
  clr  r3
207
    LCD_delay_inner:
208
    dec  r3
209
    brne  LCD_delay_inner
210
  dec  r2
211
  brne  LCD_delay_outer
212
  ret
213
214
LCD_init:     
215
;**** for the most LCD you must write 3times a dummy command before you change to 4Bit***
216
;this is corrected by www.bellibot.com :-)) - before !you have only one LineLCD ***
217
  
218
  ;ldi  temp, 0b00001110  ;control lines are output, rest is input
219
  in temp,LCD_DDR
220
  andi temp,0b00001111    ;LCD pins input
221
  out LCD_DDR,temp
222
  in temp,LCDS_DDR
223
  ori     temp, (1<<LCD_RS)|(1<<LCD_RW)|(1<<LCD_E) ;controllpins output
224
  out  LCDS_DDR, temp
225
  
226
  rcall  LCD_delay    ;
227
  ldi  arg, 0x30      ;
228
  rcall  LCD_command8    
229
230
  rcall  LCD_delay
231
  ldi  arg, 0x30    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** DUMMY ***
232
  rcall  LCD_command8    ;
233
  
234
  
235
  rcall  LCD_delay    
236
  ldi  arg, 0x30      
237
  rcall  LCD_command8    
238
239
  rcall  LCD_delay    ;first, we'll tell the LCD that we want to use it
240
  ldi  arg, 0x20      ;in 4-bit mode.
241
  rcall  LCD_command8    ;LCD is still in 8-BIT MODE while writing this command!!!
242
243
  
244
  rcall  LCD_delay
245
  ldi  arg, 0x28    ;NOW: 2 lines, 5*7 font, 4-BIT MODE!     ** this change to 4bit 2 lines **
246
  rcall  LCD_command    ;after this point you don't can change anything 'show HD44780 Datasheet'
247
248
  rcall  LCD_wait
249
  ldi  arg, 0x0F    ;now proceed as usual: Display on, cursor on, blinking
250
  rcall  LCD_command
251
  
252
  rcall  LCD_wait
253
  ldi  arg, 0x01    ;clear display, cursor -> home
254
  rcall  LCD_command
255
  
256
  rcall  LCD_wait
257
  ldi  arg, 0x06    ;auto-inc cursor
258
  rcall  LCD_command
259
  ret
260
261
;******************************************
262
; clear Displays
263
LCD_clear:
264
           push arg
265
       ldi   arg, 0b00000001      ; Display clear
266
           rcall LCD_command
267
           rcall  LCD_wait
268
           pop arg
269
       ret
270
 
271
 ; Cursor Home
272
LCD_home:
273
           push arg
274
       ldi   arg, 0b00000010      ; Cursor Home
275
           rcall LCD_command
276
           rcall  LCD_wait
277
           pop arg
278
       ret
279
;set cursor pos
280
LCD_pos:
281
    sbr arg,0b10000000 ; Set DD-RAM-Adress
282
    rcall LCD_command
283
    rcall  LCD_wait
284
    ret
285
286
;*****************************************************
287
; Display at the position in arg the string starting at Z (null-term.)
288
;
289
LCD4ZTxt:
290
  sbr arg,0b10000000 ; Set DD-RAM-Adress
291
  rcall LCD_command
292
  rcall  LCD_wait
293
LCD4ZTxt1:
294
  lpm ; Get a char
295
  tst R0 ; Null-Char?
296
  breq LCD4ZTxtR
297
  mov arg,R0
298
  rcall LCD_putchar ; display the cahr
299
  rcall  LCD_wait
300
  adiw ZL,1 ; next char
301
  rjmp LCD4ZTxt1 ; do it again
302
LCD4ZTxtR:
303
  ret
304
;**********************************************************************
305
;
306
; Eine 8 Bit Zahl ohne Vorzeichen hexadezimal ausgeben
307
;
308
; Übergabe:            Zahl im Register arg
309
; veränderte Register: keine
310
;
311
lcd_number_hex:
312
           swap  arg
313
           rcall lcd_number_hex_digit
314
           swap  arg
315
 
316
lcd_number_hex_digit:
317
           push  arg
318
 
319
           andi  arg, $0F
320
           cpi   arg, 10
321
           brlt  lcd_number_hex_digit_1
322
           subi  arg, -( 'A' - '9' - 1 ) ; es wird subi mit negativer Konstante verwendet, weil es kein addi gibt
323
lcd_number_hex_digit_1:
324
           subi  arg, -'0'               ; ditto
325
           rcall  lcd_putchar
326
           rcall  LCD_wait
327
           pop   arg
328
           ret
329
;*********************************************************************
330
;
331
; Eine 8 Bit Zahl dezimal ohne Vorzeichen ausgeben
332
;
333
; Übergabe:            Zahl im Register arg
334
; veränderte Register: keine
335
;
336
lcd_number:
337
           ;push  temp            ; die Funktion verändert temp2, also sichern
338
                                  ; wir den Inhalt, um ihn am Ende wieder
339
                                  ; herstellen zu können
340
 
341
           mov   arg2,arg     ; das Register temp1 frei machen
342
                                  ; abzählen wieviele Hunderter
343
                                  ; in der Zahl enthalten sind
344
           ldi   arg, '0'
345
lcd_number_1:
346
           subi  arg2, 100       ; 100 abziehen
347
           brcs  lcd_number_2     ; ist dadurch ein Unterlauf entstanden?
348
           inc   arg            ; Nein: 1 Hunderter mehr ...
349
           rjmp  lcd_number_1     ; ... und ab zur nächsten Runde
350
;
351
                                  ; die Hunderterstelle ausgeben
352
lcd_number_2:
353
           rcall LCD_putchar
354
           rcall LCD_wait
355
       subi  arg2, -100      ; 100 wieder dazuzählen, da die
356
                              ; vorherhgehende Schleife 100 zuviel
357
                  ; abgezogen hat
358
 
359
                                  ; abzählen wieviele Zehner in
360
                  ; der Zahl enthalten sind
361
           ldi   arg, '0'
362
lcd_number_3:
363
           subi  arg2, 10        ; 10 abziehen
364
           brcs  lcd_number_4     ; ist dadurch ein Unterlauf enstanden?
365
           inc   arg            ; Nein: 1 Zehner mehr ...
366
           rjmp  lcd_number_3     ; ... und ab zur nächsten Runde
367
 
368
                              ; die Zehnerstelle ausgeben
369
lcd_number_4:
370
           rcall LCD_putchar
371
           rcall LCD_wait
372
       subi  arg2, -10       ; 10 wieder dazuzählen, da die
373
                              ; vorhergehende Schleife 10 zuviel
374
                  ; abgezogen hat
375
 
376
                                  ; die übrig gebliebenen Einer
377
                  ; noch ausgeben
378
           ldi   arg, '0'       ; die Zahl in temp2 ist jetzt im Bereich
379
           add   arg, arg2     ; 0 bis 9. Einfach nur den ASCII Code für
380
           rcall LCD_putchar         ; '0' dazu addieren und wir erhalten dierekt
381
           rcall LCD_wait                       ; den ASCII Code für die Ziffer
382
 
383
           ;pop   temp            ; den gesicherten Inhalt von temp2 wieder herstellen
384
           ret                    ; und zurück

von Mike (Gast)


Lesenswert?

Fritz Bie schrieb:
> Illegal use of undefined or forward referenced symbol
> 'LCDS_DDR'

Du solltest dem Compiler LCDS_DDR irgendwie bekannt machen.

p.s.
Ruft das Wort "Dateianhang" irgendwelche Assoziation bei dir wach?

von Fritz B. (kleinfritzchen)


Lesenswert?

tut mir leid aber ich versteh überhaupt nicht was du mit "Dateianhang" 
meinst. Ich hab auch keine Ahnung wie man diese Variablen dem Compiler 
bekannt macht.
Das ganze funktioniert natürlich mit einer weiteren Datei in der eine 
main ist und dort sind die in der Datei aufgeführten sachen:
;.equ   LCD_PORT = PORTD
;.equ   LCD_DDR  = DDRD
;.equ  LCDS_PORT = PORTD
;.equ  LCDS_DDR  = DDRD

;.equ  LCD_RS  = 1
;.equ  LCD_RW  = 2
;.equ  LCD_E  = 3


;.def  temp  = r16
;.def  arg    = r17    ;argument for calling subroutines
;.def  arg2  = r18    ;argument for mathematics
;.def  return  = r19    ;return value from subroutines
natürlich definiert....
allerdings hab ich das .include vor der Definition, das probier ich heut 
Abend mal aus, vielleicht liegt es ja da dran.

von Georg G. (df2au)


Lesenswert?

Du weißt aber schon, dass ein ; den Rest der Zeile zum Kommentar 
erklärt? Insofern sind deine "Definitionen" nur schmückendes Beiwerk.

Abgesehen davon zeigen mir diese Zeilen

; the other LCd data lines can be left open or tied to ground.
; the pin Vo can fit to GND for maximum of contrast

dass der Autor entweder das Datenblatt nicht gelesen oder nicht 
verstanden hat. Die Spannung an Vo solltest du auf jeden Fall 
einstellbar machen und die nicht benutzten Pins am LCD lass bitte offen.

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.