Forum: Mikrocontroller und Digitale Elektronik LCD an PORTF von Atmega128A - PINS vertauschen


von Benjamin (Gast)


Lesenswert?

Hallo zusammen,

ich betreibe an PORTF eines ATmega128A ein LCD im 4 Bit Modus.
Allerdings nicht an den Pins 0 - 5, sondern an den Pins 2 - 7 (ist durch 
das Platinenlayout so gegeben).

An den Pins 0 - 5 funktioniert das Display (Testplatine).

Um das LCD an den Pins 2 - 7 zu betrieben war die Idee, vor der Übergabe 
an den Port alles um 2 Stellen nach links zu verschieben. Und an dieser 
Stelle gibt es Probleme (ebenfalls mit der Testplatine). Code lässt sich 
kompilieren. Allerdings zeigt das Display nur zwei Striche im ersten 
Element.

Ich benutze Code aus dem Netz und habe diesen um die Funktion portout 
erweitert (siehe Anhang). Dies funktioniert auch, wenn das Display an 
den Pins 0 - 5 angeschlossen ist (zurzeit auskommentiert)

Jemand eine Idee.

Danke!

Viele Grüße
Benjamin
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                 LCD-Routinen                ;;
3
;;                 ============                ;;
4
;;              (c)andreas-s@web.de            ;;
5
;;                                             ;;
6
;; 4bit-Interface                              ;;
7
;; DB4-DB7:       PD0-PD3                      ;;
8
;; RS:            PD5                          ;;
9
;; E:             PD4                          ;;
10
;;                                             ;;
11
;; Takt:          4 MHz                        ;;
12
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
 
14
 ; .equ definiert ein Symbol und dessen Wert
15
.equ LCD_PORT = PORTF
16
.equ LCD_DDR  = DDRF
17
.equ PIN_E    = 4
18
.equ PIN_RS   = 5
19
.equ XTAL  = 4000000
20
 
21
 ;sendet ein Datenbyte an das LCD
22
lcd_data:
23
           push temp1
24
       push temp2
25
       
26
       mov temp2, temp1             ; "Sicherungskopie" für
27
                                        ; die Übertragung des 2.Nibbles
28
           swap temp1                   ; Vertauschen
29
           andi temp1, 0b00001111       ; oberes Nibble auf Null setzen
30
           sbr temp1, 1<<PIN_RS              ; entspricht 0b00010000 (Anm.1)
31
           ;sts LCD_PORT, temp1             ; ausgeben
32
       mov temp4, temp1
33
       rcall portout
34
           rcall lcd_enable             ; Enable-Routine aufrufen
35
                                        ; 2. Nibble, kein swap da es schon
36
                                        ; an der richtigen stelle ist
37
           andi temp2, 0b00001111       ; obere Hälfte auf Null setzen 
38
           sbr temp2, 1<<PIN_RS              ; entspricht 0b00010000
39
           ;sts LCD_PORT, temp2             ; ausgeben
40
          mov temp4, temp2
41
       rcall portout
42
           rcall lcd_enable             ; Enable-Routine aufrufen
43
           rcall delay50us              ; Delay-Routine aufrufen
44
       pop temp2
45
       pop temp1
46
           ret                          ; zurück zum Hauptprogramm
47
 
48
 ; sendet einen Befehl an das LCD
49
lcd_command:                            ; wie lcd_data, nur RS=0
50
           push temp1
51
       push temp2
52
       mov temp2, temp1
53
           swap temp1
54
           andi temp1, 0b00001111
55
           ;sts LCD_PORT, temp1
56
       mov temp4, temp1
57
       rcall portout
58
           rcall lcd_enable
59
           andi temp2, 0b00001111
60
           ;sts LCD_PORT, temp2
61
       mov temp4, temp2
62
       rcall portout
63
           rcall lcd_enable
64
           rcall delay50us
65
       pop temp2
66
       pop temp1
67
           ret
68
 
69
 ; erzeugt den Enable-Puls
70
 ;
71
 ; Bei höherem Takt (>= 8 MHz) kann es notwendig sein, 
72
 ; vor dem Enable High 1-2 Wartetakte (nop) einzufügen. 
73
 ; Siehe dazu http://www.mikrocontroller.net/topic/81974#685882
74
lcd_enable:
75
           lds temp4, LCD_PORT
76
       sbr temp4, 1<<PIN_E                 ; Enable high
77
       rcall portout
78
           nop                          ; mindestens 3 Taktzyklen warten
79
           nop
80
           nop
81
           lds temp4, LCD_PORT
82
       cbr temp4, 1<<PIN_E                 ; Enable high
83
       rcall portout
84
           ret                          ; Und wieder zurück                     
85
 
86
 ; Pause nach jeder Übertragung
87
delay50us:                              ; 50µs Pause (bei 4 MHz)
88
           push temp1
89
       ldi  temp1, ( XTAL * 50 / 3 ) / 1000000
90
delay50us_:dec  temp1
91
           brne delay50us_
92
       pop temp1           
93
       ret                          ; wieder zurück
94
 
95
 ; Längere Pause für manche Befehle
96
delay5ms:                               ; 5ms Pause (bei 4 MHz)
97
           push temp1
98
       push temp2           
99
       ldi  temp1, ( XTAL * 5 / 607 ) / 1000
100
WGLOOP0:   ldi  temp2, $C9
101
WGLOOP1:   dec  temp2
102
           brne WGLOOP1
103
           dec  temp1
104
           brne WGLOOP0
105
       pop temp1
106
       pop temp2
107
           ret                          ; wieder zurück
108
 
109
 ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
110
lcd_init:
111
           push temp1
112
       push temp3             
113
       ldi temp1, 0xFF    ;Port D = Ausgang
114
           sts LCD_DDR, temp1
115
       ldi  temp3,50
116
powerupwait:
117
           rcall  delay5ms
118
           dec  temp3
119
           brne powerupwait
120
           ldi temp1, 0b00000011        ; muss 3mal hintereinander gesendet
121
           ;sts LCD_PORT, temp1             ; werden zur Initialisierung
122
       mov temp4, temp1
123
       rcall portout
124
           rcall lcd_enable             ; 1
125
           rcall delay5ms
126
           rcall lcd_enable             ; 2
127
           rcall delay5ms
128
           rcall lcd_enable             ; und 3!
129
           rcall delay5ms
130
           ldi temp1, 0b00000010        ; 4bit-Modus einstellen
131
           ;sts LCD_PORT, temp1
132
       mov temp4, temp1
133
       rcall portout
134
           rcall lcd_enable
135
           rcall delay5ms
136
           ldi temp1, 0b00101000        ; 4Bit / 2 Zeilen / 5x8
137
           rcall lcd_command
138
           ldi temp1, 0b00001111        ; Display ein / Cursor aus / kein Blinken
139
           rcall lcd_command
140
           ldi temp1, 0b00000100        ; inkrement / kein Scrollen
141
           rcall lcd_command
142
       pop temp3
143
       pop temp1
144
           ret
145
 
146
 ; Sendet den Befehl zur Löschung des Displays
147
lcd_clear:
148
           push temp1
149
           ldi temp1, 0b00000001   ; Display löschen
150
           rcall lcd_command
151
           rcall delay5ms
152
       pop temp1
153
           ret
154
 
155
 ; Sendet den Befehl: Cursor Home
156
lcd_home:
157
           push temp1           
158
       ldi temp1, 0b00000010   ; Cursor Home
159
           rcall lcd_command
160
           rcall delay5ms
161
       pop temp1
162
           ret
163
164
 ; Einen konstanten Text aus dem Flash Speicher
165
 ; ausgeben. Der Text wird mit einer 0 beendet
166
lcd_flash_string:
167
           push  temp1
168
           push  ZH
169
           push  ZL
170
 
171
lcd_flash_string_1:
172
           lpm   temp1, Z+
173
           cpi   temp1, 0
174
           breq  lcd_flash_string_2
175
           rcall  lcd_data
176
           rjmp  lcd_flash_string_1
177
 
178
lcd_flash_string_2:
179
           pop   ZL
180
           pop   ZH
181
           pop   temp1
182
           ret
183
184
portout:
185
  lds register, LCD_PORT
186
187
  SBRC temp4, 0
188
  ori register, 0b00000100
189
  SBRS temp4, 0
190
  andi register, 0b11111011
191
192
  SBRC temp4, 1
193
  ori register, 0b00001000
194
  SBRS temp4, 1
195
  andi register, 0b11110111
196
197
  SBRC temp4, 2
198
  ori register, 0b00010000
199
  SBRS temp4, 2
200
  andi register, 0b11101111
201
202
  SBRC temp4, 3
203
  ori register, 0b00100000
204
  SBRS temp4, 3
205
  andi register, 0b11011111
206
207
  SBRC temp4, 4
208
  ori register, 0b01000000
209
  SBRS temp4, 4
210
  andi register, 0b10111111
211
212
  SBRC temp4, 5
213
  ori register, 0b10000000
214
  SBRS temp4, 5
215
  andi register, 0b01111111
216
/*
217
218
  SBRC temp4, 0
219
  ori register, 1
220
  SBRS temp4, 0
221
  andi register, 254
222
223
  SBRC temp4, 1
224
  ori register, 2
225
  SBRS temp4, 1
226
  andi register, 253
227
228
  SBRC temp4, 2
229
  ori register, 4
230
  SBRS temp4, 2
231
  andi register, 251
232
233
  SBRC temp4, 3
234
  ori register, 8
235
  SBRS temp4, 3
236
  andi register, 247
237
238
  SBRC temp4, 4
239
  ori register, 16
240
  SBRS temp4, 4
241
  andi register, 239
242
243
  SBRC temp4, 5
244
  ori register, 32
245
  SBRS temp4, 5
246
  andi register, 223
247
  */
248
  clr temp4
249
  sts LCD_PORT, register
250
  ret

von Karl H. (kbuchegg)


Lesenswert?

Was zum ....
... soll den das hier machen?
1
portout:
2
  lds register, LCD_PORT
3
4
  SBRC temp4, 0
5
  ori register, 0b00000100
6
  SBRS temp4, 0
7
  andi register, 0b11111011
8
9
  SBRC temp4, 1
10
  ori register, 0b00001000
11
  SBRS temp4, 1
12
  andi register, 0b11110111
13
14
  SBRC temp4, 2
15
  ori register, 0b00010000
16
  SBRS temp4, 2
17
  andi register, 0b11101111
18
19
  SBRC temp4, 3
20
  ori register, 0b00100000
21
  SBRS temp4, 3
22
  andi register, 0b11011111
23
24
  SBRC temp4, 4
25
  ori register, 0b01000000

du brauchst doch nur den Inhalt von temp4 um 2 Stellen nach links 
schieben, die beiden untersten Bits vom PORTF wieder einodern (damit du 
nicht unabsichtlich etwas an den beiden änderst und das ganze an den 
PORTF ausgeben. Das ganze sind grade mal überschlagsmässig 5 Anweisungen 
ohne den Return. Machs doch nicht so kompliziert.

von Benjamin (Gast)


Lesenswert?

Im Grunde macht der Code dieses hier:
1
portout:
2
  push temp2
3
  ldi temp2, 4
4
  mul   temp4, temp2
5
6
  sts LCD_PORT, r0
7
8
  pop temp2
9
  ret

Hatte es mir Schrittweise programmiert. Hilft manchmal wenn mans 
Bitweise durchgeht.
Daran scheint es aber nicht zu liegen...

von prof.dr.schlau (Gast)


Lesenswert?

Ist vielleicht noch JTag o.ä. aktiv? Andere Vorbelegung der Pins (kenne 
den 128 nun nicht speziell), ist aber gerne ein Stolperstein

von Benjamin (Gast)


Lesenswert?

JTAG ist deaktiviert.

von prof.dr.schlau (Gast)


Lesenswert?

Richtig doofe Frage: Hast du beim Verschieben diese Pins angepasst:

.equ PIN_E    = 4
.equ PIN_RS   = 5

??

von Benjamin B. (ghosttree)


Lesenswert?

Danke für den Hinweis.

Habe die Pins angepasst, allerdings nur bei der Ausgabe.
Bei lcd_enable wird jedoch der Inhalt von LCD_PORT gelesen. Habe diesen 
jetzt nach dem Einlesen durch 4 geteilt und funktioniert es :)

Vielen Dank!

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.