Forum: Mikrocontroller und Digitale Elektronik AVR Studio 5 Assembler .include


von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich bin neu in der Mikrocontrollerprogrammierung und wollte jetzt mal 
ein LCD ansteuern. Dazu habe ich mal das Programm aus dem Tutorial zum 
Einsteigen "geklaut" und wollte es jetzt mal ausprobieren.

Allerdings spuckt mir AVR-Studio beim Assemblieren immer eine 
Fehlermeldung aus (siehe Anhang).

Ich bin mir aber auch nicht sicher ob ich alles richtig gemacht habe 
(blicke nicht ganz durch was mit Projekt und Solution jetzt eigentlich 
gemeint ist). Habe beim Start von AVR-Studio 5 "New Project" geklickt 
und dann meinen Kontroller gewählt, dann den LCD-Testprogramm Code 
reinkopiert. Anschliesend Rechtsklick auf AVRAssembler7 -> Add -> New 
Item -> Assembler file und dort den LCD-Routinen Code reinkopiert und 
die Datei LCD-Routinen genannt.

Was mache ich falsch?


Gruß,
Thomas


PS: wenn ich den Inhalt von LCD-Routinen.asm direkt unter mein 
"Hauptprogramm" kopiere geht es.

von Horst (Gast)


Lesenswert?

Ich habe das Programm zwar noch nie verwendet, aber setz zum testen mal 
bitte alle .include-Direktive an den Anfang des Programmes...

von Thomas (Gast)


Lesenswert?

Hi, danke für den Tipp!

dann lässt es sich zwar assemblieren aber läuft nicht wenn man es auf 
den MC programmiert. (vermute, dass er den Inhalt der Include Datei auch 
genau an die Stelle des .include Befehlts schreibt, also noch vor das 
Hauptprogramm wo sie eigentlich nicht hin gehören)

Weiß sonst niemand eine Lösung?

von Horst (Gast)


Lesenswert?

Was ist denn konkret der Inhalt der "LCD-Routinen"? Die Fehlermeldungen 
besagen wohl, dass etwas mit den Sprungmarken "lcd_clear" und "lcd_data" 
nicht stimmt.

von Karl H. (kbuchegg)


Lesenswert?

Auf deinem Screenshot ist das nicht erkennbar (und genau darum sind 
Bilder immer blöd), aber hast du die letzte Zeile, die mit dem .include 
mit einem Zeilenvorschub abgeschlossen?
Manche Assembler sind da pingelig und werten as ansonsten nicht als 
vollständige Zeile.

Wenns das auch nicht ist: poste deinen Source Code, damit jemand anderer 
das mal durch sein System durchjagen kann.

von Thomas (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Auf deinem Screenshot ist das nicht erkennbar (und genau darum sind
> Bilder immer blöd), aber hast du die letzte Zeile, die mit dem .include
> mit einem Zeilenvorschub abgeschlossen?
> Manche Assembler sind da pingelig und werten as ansonsten nicht als
> vollständige Zeile.

Ich flipp aus... genau das wars :) Vielen Dank! Jibbiee

von Der Ben (Gast)


Lesenswert?

Bei mir funktioniert es leider nicht.
Weder mit .include, noch mit einfügen des Code nach dem Hauptprogramm.
Wo liegt das Problem?
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;          Hauptprogramm               ;
3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4
5
.include "m328Pdef.inc"
6
7
8
.def temp1 = r16
9
.def temp2 = r17
10
.def temp3 = r18
11
12
13
           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
14
           out SPL, temp1
15
           ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
16
           out SPH, temp1
17
18
           ldi temp1, 0xFF    ;Port D = Ausgang
19
           out DDRD, temp1
20
21
           rcall lcd_init     ;Display initialisieren
22
           rcall lcd_clear    ;Display löschen
23
24
           ldi temp1, 'T'     ;Zeichen anzeigen
25
           rcall lcd_data
26
27
           ldi temp1, 'e'     ;Zeichen anzeigen
28
           rcall lcd_data
29
           
30
           ldi temp1, 's'     ;Zeichen anzeigen
31
           rcall lcd_data
32
33
           ldi temp1, 't'     ;Zeichen anzeigen
34
           rcall lcd_data
35
36
loop:   
37
       rjmp loop
38
39
40
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41
;;                 LCD-Routinen                ;;
42
;;                 ============                ;;
43
;;              (c)andreas-s@web.de            ;;
44
;;                                             ;;
45
;; 4bit-Interface                              ;;
46
;; DB4-DB7:       PD0-PD3                      ;;
47
;; RS:            PD4                          ;;
48
;; E:             PD5                          ;;
49
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
 
51
.def temp2 = r22
52
.def temp3 = r23
53
 
54
.equ LCD_PORT = PORTD
55
.equ LCD_DDR  = DDRD
56
.equ PIN_RS   = 4
57
.equ PIN_E    = 5
58
59
.ifndef XTAL
60
.equ XTAL = 4000000
61
.endif
62
63
 ;sendet ein Datenbyte an das LCD
64
lcd_data:
65
           push  temp2
66
           push  temp3
67
           mov   temp2, temp1            ; "Sicherungskopie" für
68
                                         ; die Übertragung des 2.Nibbles
69
           swap  temp1                   ; Vertauschen
70
           andi  temp1, 0b00001111       ; oberes Nibble auf Null setzen
71
           sbr   temp1, 1<<PIN_RS        ; entspricht 0b00010000
72
           in    temp3, LCD_PORT
73
           andi  temp3, 0x80
74
           or    temp1, temp3
75
           out   LCD_PORT, temp1         ; ausgeben
76
           rcall lcd_enable              ; Enable-Routine aufrufen
77
                                         ; 2. Nibble, kein swap da es schon
78
                                         ; an der richtigen stelle ist
79
           andi  temp2, 0b00001111       ; obere Hälfte auf Null setzen 
80
           sbr   temp2, 1<<PIN_RS        ; entspricht 0b00010000
81
           or    temp2, temp3
82
           out   LCD_PORT, temp2         ; ausgeben
83
           rcall lcd_enable              ; Enable-Routine aufrufen
84
           rcall delay50us               ; Delay-Routine aufrufen
85
86
           pop   temp3
87
           pop   temp2
88
           ret                           ; zurück zum Hauptprogramm
89
 
90
 ; sendet einen Befehl an das LCD
91
lcd_command:                            ; wie lcd_data, nur ohne RS zu setzen
92
           push  temp2
93
           push  temp3
94
95
           mov   temp2, temp1
96
           swap  temp1
97
           andi  temp1, 0b00001111
98
           in    temp3, LCD_PORT
99
           andi  temp3, 0x80
100
           or    temp1, temp3
101
           out   LCD_PORT, temp1
102
           rcall lcd_enable
103
           andi  temp2, 0b00001111
104
           or    temp2, temp3
105
           out   LCD_PORT, temp2
106
           rcall lcd_enable
107
           rcall delay50us
108
 
109
           pop   temp3
110
           pop   temp2
111
           ret
112
 
113
 ; erzeugt den Enable-Puls
114
lcd_enable:
115
           sbi LCD_PORT, PIN_E          ; Enable high
116
           nop                          ; 3 Taktzyklen warten
117
           nop
118
           nop
119
           cbi LCD_PORT, PIN_E          ; Enable wieder low
120
           ret                          ; Und wieder zurück                     
121
 
122
 ; Pause nach jeder Übertragung
123
delay50us:                              ; 50us Pause
124
           ldi  temp1, ( XTAL * 50 / 3 ) / 1000000
125
delay50us_:
126
           dec  temp1
127
           brne delay50us_
128
           ret                          ; wieder zurück
129
 
130
 ; Längere Pause für manche Befehle
131
delay5ms:                               ; 5ms Pause
132
           ldi  temp1, ( XTAL * 5 / 607 ) / 1000
133
WGLOOP0:   ldi  temp2, $C9
134
WGLOOP1:   dec  temp2
135
           brne WGLOOP1
136
           dec  temp1
137
           brne WGLOOP0
138
           ret                          ; wieder zurück
139
 
140
 ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
141
lcd_init:
142
           push  temp1
143
           in    temp1, LCD_DDR
144
           ori   temp1, (1<<PIN_E) | (1<<PIN_RS) | 0x0F
145
           out   LCD_DDR, temp1
146
147
           ldi   temp3,6
148
powerupwait:
149
           rcall delay5ms
150
           dec   temp3
151
           brne  powerupwait
152
           ldi   temp1,    0b00000011   ; muss 3mal hintereinander gesendet
153
           out   LCD_PORT, temp1        ; werden zur Initialisierung
154
           rcall lcd_enable             ; 1
155
           rcall delay5ms
156
           rcall lcd_enable             ; 2
157
           rcall delay5ms
158
           rcall lcd_enable             ; und 3!
159
           rcall delay5ms
160
           ldi   temp1,    0b00000010   ; 4bit-Modus einstellen
161
           out   LCD_PORT, temp1
162
           rcall lcd_enable
163
           rcall delay5ms
164
           ldi   temp1,    0b00101000   ; 4 Bot, 2 Zeilen
165
           rcall lcd_command
166
           ldi   temp1,    0b00001100   ; Display on, Cursor off
167
           rcall lcd_command
168
           ldi   temp1,    0b00000100   ; endlich fertig
169
           rcall lcd_command
170
171
           pop   temp1
172
           ret
173
 
174
 ; Sendet den Befehl zur Löschung des Displays
175
lcd_clear:
176
           push  temp1
177
           ldi   temp1,    0b00000001   ; Display löschen
178
           rcall lcd_command
179
           rcall delay5ms
180
           pop   temp1
181
           ret
182
183
 ; Cursor Home
184
lcd_home:
185
           push  temp1
186
           ldi   temp1,    0b00000010   ; Cursor Home
187
           rcall lcd_command
188
           rcall delay5ms
189
           pop   temp1
190
           ret
191
192
 ; Einen konstanten Text aus dem Flash Speicher
193
 ; ausgeben. Der Text wird mit einer 0 beendet
194
lcd_flash_string:
195
           push  temp1
196
197
lcd_flash_string_1:
198
           lpm   temp1, Z+
199
           cpi   temp1, 0
200
           breq  lcd_flash_string_2
201
           rcall  lcd_data
202
           rjmp  lcd_flash_string_1
203
204
lcd_flash_string_2:
205
           pop   temp1
206
           ret
207
208
 ; Eine Zahl aus dem Register temp1 dezimal ausgeben
209
lcd_number:
210
           push  temp1
211
           push  temp2
212
           push  temp3
213
214
           mov   temp2, temp1
215
                                  ; abzählen wieviele Hunderter
216
                                          ; in der Zahl enthalten sind
217
           ldi   temp1, '0'
218
lcd_number_1:
219
           subi  temp2, 100
220
           brcs  lcd_number_2
221
           inc   temp1
222
           rjmp  lcd_number_1
223
                                          ;
224
                                          ; die Hunderterstelle ausgeben
225
lcd_number_2:
226
           rcall lcd_data
227
           subi  temp2, -100              ; 100 wieder dazuzählen, da die
228
                                          ; vorherhgehende Schleife 100 zuviel
229
                                          ; abgezogen hat
230
231
                                          ; abzählen wieviele Zehner in
232
                                          ; der Zahl enthalten sind
233
           ldi   temp1, '0'
234
lcd_number_3:
235
           subi  temp2, 10
236
           brcs  lcd_number_4
237
           inc   temp1
238
           rjmp  lcd_number_3
239
240
                                          ; die Zehnerstelle ausgeben
241
lcd_number_4:
242
           rcall lcd_data
243
           subi  temp2, -10               ; 10 wieder dazuzählen, da die
244
                                          ; vorhergehende Schleife 10 zuviel
245
                                          ; abgezogen hat
246
247
                                          ; die übrig gebliebenen Einer
248
                                          ; noch ausgeben
249
           ldi   temp1, '0'
250
           add   temp1, temp2
251
           rcall lcd_data
252
253
           pop   temp3
254
           pop   temp2
255
           pop   temp1
256
           ret
257
258
; eine Zahl aus dem Register temp1 hexadezimal ausgeben
259
lcd_number_hex:
260
           push  temp1
261
262
           swap  temp1
263
           andi  temp1, $0F
264
           rcall lcd_number_hex_digit
265
266
           pop   temp1
267
           push  temp1
268
269
           andi  temp1, $0F
270
           rcall lcd_number_hex_digit
271
272
           pop   temp1
273
           ret
274
275
lcd_number_hex_digit:
276
           cpi   temp1, 10
277
           brlt  lcd_number_hex_digit_1
278
           subi  temp1, -( 'A' - '9' - 1 )
279
lcd_number_hex_digit_1:
280
           subi  temp1, -'0'
281
           rcall  lcd_data
282
           ret



oder



1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;          Hauptprogramm               ;
3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4
5
.include "m328Pdef.inc"
6
7
8
.def temp1 = r16
9
.def temp2 = r17
10
.def temp3 = r18
11
12
13
           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
14
           out SPL, temp1
15
           ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
16
           out SPH, temp1
17
18
           ldi temp1, 0xFF    ;Port D = Ausgang
19
           out DDRD, temp1
20
21
           rcall lcd_init     ;Display initialisieren
22
           rcall lcd_clear    ;Display löschen
23
24
           ldi temp1, 'T'     ;Zeichen anzeigen
25
           rcall lcd_data
26
27
           ldi temp1, 'e'     ;Zeichen anzeigen
28
           rcall lcd_data
29
           
30
           ldi temp1, 's'     ;Zeichen anzeigen
31
           rcall lcd_data
32
33
           ldi temp1, 't'     ;Zeichen anzeigen
34
           rcall lcd_data
35
36
loop:   
37
       rjmp loop
38
39
.include "lcd-routines.asm"

Hab die "lcd-routines.asm" im Solutionexplorer eingefügt und hab das 
selbige Problem wie oben der Thomas.
Wenn ich den Code nach dem Hauptprogramm einfüge kommt auch:

Warning  1  .def: 'temp2' redefinition (r17->r22) 
C:\Users\Ben\Documents\Atmel Studio\6.2\LCD Tests\LCD Tests\LCD 
Tests.asm  51  0  LCD Tests
Warning  3  .def: 'temp3' redefinition (r18->r23) 
C:\Users\Ben\Documents\Atmel Studio\6.2\LCD Tests\LCD Tests\LCD 
Tests.asm  52  0  LCD Tests
Message  2  previous definition of 'temp2'  C:\Users\Ben\Documents\Atmel 
Studio\6.2\LCD Tests\LCD Tests\LCD Tests.asm  9  1  LCD Tests
Message  4  previous definition of 'temp3'  C:\Users\Ben\Documents\Atmel 
Studio\6.2\LCD Tests\LCD Tests\LCD Tests.asm  10  1  LCD Tests

von hagi (Gast)


Lesenswert?

In deinem Programnm werden "temp2" und "temp" 3 mal(!) definiert.
Variable müssen eindeutig (einmalig) definiert werden. Wie soll der 
Assembler/Compiler denn wissen welches "temp2" du benutzen willst?

Ausnahmen sind lokale Variablen, aber ob das dein Assembler kann weiß 
ich jetzt auch ncht (ich benutze andere Controller).

von Arrrgh (Gast)


Lesenswert?

Der Ben schrieb:
> Wo liegt das Problem?

Dass du gerade einen uralten Threads gekapert hast, dessen Länge durch 
mißachten der Funktion für Anhänge um 500 Prozent erhöht hast und dein 
Problem außer "es geht nicht" überhaupt nichts mit der Fehlermeldung des 
to zu tun hat.

von Der Ben (Gast)


Lesenswert?

Der Code ist wohl wirklich etwas lang.
Heute Nacht im halbschlaf gar nicht so realisiert. Sry!
Nächstes Mal gehts in den Anhang damit.
Allerdings habe ich bis auf die Variablen-Geschichte genau das gleiche 
Problem wie der TO.

von TriHexagon (Gast)


Lesenswert?

Der Ben schrieb:
> .include "lcd-routines.asm"

Bin ich der Einzige der das für bedenklich hält. Wofür gibts Linker? Die 
sind auch etwas schlauer als der dumme Präprozessor.

von spess53 (Gast)


Lesenswert?

Hi

>Bin ich der Einzige der das für bedenklich hält. Wofür gibts Linker? Die
>sind auch etwas schlauer als der dumme Präprozessor.

Welchen Linker vom AVR-Assembler meinst du?

MfG Spess

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.