Forum: Mikrocontroller und Digitale Elektronik LCD-Display Stack-Fehler


von Martin K. (spyro07)


Lesenswert?

Hi,

ich verusche ein LCD anzusteuern.
Das LCD ist leider noch nicht da, aber ich habe  beim Simulieren bemerkt 
das irgendwie der Stack überläuft.
Nachdem ich gleich nach der Stack-Initialisierung (nur zum Test) nachdem 
ich die Adresse in den z-Pointer geladen habe mit rcall lcd_send_Data 
das UP aufrufe.
Dort geht es auch noch durch, durch das weitere UP wait5ms geht es auch 
noch.
Dann wenn das ret von lcd_send_data ausgeführt wird, lande ich wieder 
bei init.

Woran liegt das?

Habe ich irgendwo veressen wieder ein Register zurück zu holen, oder 
derartiges?
Mir fällt nämlich da nichts auf, was ich vergessen haben könnte.

Wäre gut wenn mir da jemand helfen könnte.
1
;********************************:
2
;* Display-Ansteuerung ATMEGA16  *;
3
;*    PA0    DB4          *;   
4
;*   PA1  DB5          *;
5
;*   PA2  DB6          *;
6
;*   PA3  DB7          *;
7
;*   PA4  RS          *;
8
;*   PA5  E          *;
9
;********************************;  
10
.include   "m16def.inc"
11
12
.def     temp    = r16
13
.def  temp1    = r17
14
.def  temp2    = r18
15
.def  lcd_data  = r19
16
17
.equ  LCD_PORT  =  PORTA
18
.equ  XTAL    =  16000000 
19
20
  rjmp init                 ; Reset Handler                           
21
22
23
init:
24
    ldi     temp, LOW(RAMEND)                ; Stackpointer initialisieren
25
     out     SPL, temp
26
     ldi     temp, HIGH(RAMEND)
27
    out     SPH, temp
28
29
  ldi    temp, $FF
30
  out    PORTA, temp
31
32
   ldi   ZL, LOW(menu*2)         ; Adresse des Strings in den
33
    ldi   ZH, HIGH(menu*2)        ; Z-Pointer laden
34
  rcall  lcd_text
35
36
lcd_init:
37
     ldi    temp,8          ; 30ms Power-On-Wait
38
powerupwait:
39
    rcall    delay5ms
40
    dec    temp
41
    brne   powerupwait
42
    
43
    ldi     temp, 0b00000010     ; pad byte
44
    out     LCD_PORT, temp
45
    rcall   lcd_enable
46
    rcall   delay50us
47
    rcall   lcd_enable
48
    rcall   delay50us
49
    rcall   lcd_enable
50
    rcall   delay50us
51
52
53
    ldi   temp, 0b01100000     ; function set
54
    rcall   lcd_command
55
    rcall   delay50us
56
   
57
    ldi   temp, 0b00001111     ; display on
58
    rcall   lcd_command
59
    rcall   delay50us
60
61
  rcall   lcd_clear
62
63
    ldi   temp, 0b00000111     ; entry mode set
64
    rcall   lcd_command
65
  rcall   delay50us
66
67
     ldi   ZL, LOW(menu*2)         ; Adresse des Strings in den
68
    ldi   ZH, HIGH(menu*2)        ; Z-Pointer laden
69
  rcall  lcd_text
70
71
loop:
72
 
73
74
  rjmp  loop 
75
76
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;
77
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UP´s für LCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
78
79
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Befehl an LCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
80
lcd_command:
81
  push  temp
82
  mov    temp, lcd_data                            ; wie lcd_data, nur ohne RS zu setzen
83
  mov     temp1, temp
84
    swap    temp1
85
    andi    temp1, 0b00001111
86
    out     LCD_PORT, temp1
87
    rcall   lcd_enable
88
    
89
  andi    temp, 0b00001111
90
    out     LCD_PORT, temp
91
    rcall   lcd_enable
92
    rcall   delay50us
93
    pop     temp
94
    ret
95
96
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Datenbyte an LCD;;;;;;;;;;;;;;;;;;;;;;;;;;;
97
lcd_send_data:
98
     push    temp
99
     push    temp1
100
   
101
     mov    temp, lcd_data  
102
     mov     temp1, temp            
103
                                   
104
     swap   temp1                  
105
     andi   temp1, 0b00001111       
106
     sbr   temp1, 4            
107
     out   LCD_PORT, temp1         
108
     rcall   lcd_enable                                                     ; 2. Nibble, kein swap da es schon
109
                                   
110
     andi   temp, 0b00001111        
111
     sbr   temp, 4             
112
     out   LCD_PORT, temp         
113
     rcall   lcd_enable             
114
     rcall   delay50us              
115
  ret         
116
117
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Befehl "Display löschen";;;;;;;;;;;;;;;;;;;;
118
lcd_clear:
119
  ldi   temp, 0b00000001   
120
    rcall   lcd_command
121
    rcall   delay5ms
122
    ret
123
 
124
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Befehl "Cursor Home";;;;;;;;;;;;;;;;;;;;;;;;
125
lcd_home:
126
    ldi   temp, 0b00000010   
127
    rcall   lcd_command
128
    rcall   delay5ms
129
    ret
130
131
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LCD-Enable;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
132
lcd_enable:
133
  nop
134
  nop
135
    sbi   LCD_PORT, 5                 
136
    nop                              
137
    nop
138
    nop
139
    cbi   LCD_PORT, 5  
140
  ret                          
141
142
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Text ausgeben;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
143
lcd_text:
144
  
145
lcd_text1:
146
    lpm     lcd_data, Z+
147
    cpi     lcd_data, 0
148
    breq    lcd_text2
149
    rcall    lcd_send_data
150
    rjmp    lcd_text1
151
 
152
lcd_text2:
153
    ret
154
155
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Dezimalzahl ausgeben;;;;;;;;;;;;;;;;;;;;;;;;;;
156
lcd_number:
157
  mov    temp, lcd_data
158
    push    temp
159
    push    temp1
160
161
    mov     temp1, temp
162
  
163
    ldi     temp, '0'-1     
164
lcd_number_1:
165
    inc     temp            
166
    subi    temp1, 100       
167
    brcc    lcd_number_1     
168
                          
169
    subi    temp1, -100      
170
  mov    lcd_data, temp
171
    rcall   lcd_send_data         
172
 
173
;** Zehner  **
174
    ldi     temp, '0'-1     
175
lcd_number_2:
176
    inc     temp            
177
    subi    temp1, 10        
178
    brcc    lcd_number_2     
179
    subi    temp1, -10
180
  
181
  mov    lcd_data, temp
182
    rcall   lcd_send_data           ; die Zehnerstelle ausgeben
183
 
184
;** Einer **        
185
    ldi     temp, '0'       
186
    add     temp, temp1  
187
  mov    lcd_data, temp   
188
    rcall   lcd_send_data         
189
    pop     temp1   
190
  pop    temp
191
    ret   
192
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50us Pause;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
193
delay50us:          
194
  push  temp  
195
  push  temp1
196
delay50us_1:                         
197
  ldi    temp, 0
198
delay50us_2:
199
    dec    temp
200
    brne   delay50us_2
201
  inc    temp1  
202
  cpi    temp1, 4
203
  brne  delay50us_1
204
  
205
  pop    temp1
206
  pop   temp
207
    ret                                   
208
209
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5ms Pause;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
210
delay5ms:  
211
  push  temp
212
  push  temp1                         
213
    ldi    temp, $86
214
delay5ms_1:  
215
  ldi    temp1, $C6
216
delay5ms_2:  
217
  dec    temp1
218
    brne   delay5ms_2
219
    dec    temp
220
    brne   delay5ms_1
221
  pop    temp1
222
  pop   temp
223
    ret 
224
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;        
225
             ;              
226
 
227
228
menu:
229
           .db "~~~~Herzlich~~~~~~~Willkommen~~~", 0

von spess53 (Gast)


Lesenswert?

Hi

>lcd_send_data:
>     push    temp
>     push    temp1
.........
>     rcall   lcd_enable
>     rcall   delay50us
>  ret

MfG Spess

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Alles was du per PUSH auf den Stack beförderst mußt du auch vor dem 
RET wieder vom Stack per POP anholen.
Und wenn du dir mal deine Routine anschust siehst du: Da fehlt doch 
was...

von Martin K. (spyro07)


Lesenswert?

Ah, vielen Dank, dass habe ich nämlich nicht gesehn.
Problem gelöst.

mfg

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.