Hallo,
ich programmiere meinen ATmega32 gerade in Assembler. Nun weiss ich aber
nicht genau, wie ich das von mir gesezte T-Flag abfragen kann. (So wie
ich das versucht habe hat es nicht geklaptt - "jmp ausgabe2" wurde immer
ausgeführt ).
1
clt ;T-Flag wird in der Initialisierung gelöscht
2
....
3
in r16,SREG ;r16 mit dem Inhalt von SREG laden
4
sbrc r16,6 ;kontrollieren,ob das 6. Bit gestezt ist (T-Flag)
5
jmp ausgabe2 ;falls es nicht gesezt ist diesen Befehl überspringen
Hat jemand eine Idee woran das liegen kann? Verbesserungsvorschläge?
Gruss
Thomas
Hi
Es gibt auch bedingte Sprünge für das T-Flag -> brts/brtc.
>Hat jemand eine Idee woran das liegen kann?
Nein. In dem Codebrösel kann ich keinen Fehler entdecken.
MfG Spess
Es gibt die Befehle 'brts' und 'brtc', die springen, wenn das T-Flag
gesetzt bzw. gelöscht ist. Dein Code müßte auch funktionieren,
wahrscheinlich ist das T-flag einfach immer gesetzt. Man müßte mal den
Rest vom Code sehen.
>sbrc r16,6 ;kontrollieren,ob das 6. Bit gestezt ist (T-Flag)
Was genau soll hier passieren?
Was meinst Du mit "kontrollieren"? Es ist schon klar was Du abstrakt
"meinst", aber hier könnte zusätzlich stehen, was "konkret" passieren
soll.
Die sbxx-Befehle beeinflussen den Programmcounter.
Was soll mit dem PC unter welchen Bedingungen geschehen?
Hier noch der ganze Code.
Funktionsweise: 1. beide 7-Segmente-Anzeigen können einzeln erhöht
werden
2. beide Zähler werden multipliziert
3. Berechnung was auf jeder 7-Segmente-Anzeige angezeigt
werden soll
1
;Ansteuerung der beiden 7-Segmente-Anzeigen, sowie der Taster
2
3
;Rechner: Auf jeweils einer Anzeige kann eine Zahl hochgezählt werden
4
;und anschliessend das Produkt berechnet werden
5
6
;Für die Taster werden INT0/INT1 (==PD2/PD3) und für die 7-Segmente-Anzeigen einmal PORTA und
7
;einmal PORTB verwendet
8
9
.INCLUDE "m32def.inc" ;Deklaration für den ATmega32
10
.DEF zaehler1 = r17 ;zählvariable für 1. Anzeige
11
.DEF zaehler2 = r18 ;zählvariable für 2. Anzeige
12
.DEF zehn_ms = r19 ;für Timer0_interruptroutine
13
.DEF status = r20
14
.DEF einer = r21
15
.DEF zehner = r25
16
.DEF preloader = r23
17
.DEF uelreg = r24
18
.DEF resultat = r22
19
.DEF zz = r26
20
.CSEG ;Flash-Programm
21
rjmp initialisierung
22
.ORG INT0addr
23
jmp interrupt0
24
.ORG INT1addr
25
jmp interrupt1
26
.ORG OVF0addr
27
jmp timer0
28
;Initialisierung
29
30
initialisierung:
31
;PORTs definieren
32
ldi r16,0xFF
33
out DDRB,r16 ;PORTB als Ausgang definieren
34
out DDRA,r16 ;PORTA als Ausgang definieren
35
ldi r16,0x3F
36
out PORTA,r16 ;Am Anfang 0 auf beiden Anzeigen anzeigen
37
out PORTB,r16
38
ldi r16,0x0C
39
out PORTD,r16 ;PD2/PD3 (=INT0/INT2) Pull-Up aktivieren --> für Taster
40
ldi r16,0x00
41
out DDRD,r16 ;PORTD als Eingang definieren
42
43
44
;Variablen
45
ldi zaehler1,0x00 ;Zähler auf 0 setzen
46
ldi zaehler2,0x00
47
ldi zehn_ms, 0x00
48
ldi status,0x00
49
ldi zehner,0x0A
50
ldi einer,0x00
51
52
;Stack initialisieren
53
ldi r16,LOW(RAMEND)
54
out SPL,r16
55
ldi r16,HIGH(RAMEND)
56
out SPH,r16
57
58
;Interrupts
59
in r16,MCUCR ;lade MCUCR-Steuerregister ins Register r16
60
sbr r16,1<<ISC00 ;INT0 wird bei steigender Taktflanke ausgelöst
61
sbr r16,1<<ISC01
62
sbr r16,1<<ISC10 ;INT1 wird bei steigender Taktflanke ausgelöst
63
sbr r16,1<<ISC11
64
out MCUCR,r16 ;lade MCUCR-Register mit r16
65
in r16,GICR
66
sbr r16,1<<INT0
67
sbr r16,1<<INT1
68
out GICR, r16
69
70
;Timer
71
ldi preloader,0x70
72
out TCNT0,preloader ;Preloader 111
73
in r16,TCCR0
74
cbr r16,1<<FOC0
75
cbr r16,1<<WGM00
76
cbr r16,1<<COM01
77
cbr r16,1<<COM00
78
cbr r16,1<<WGM01 ;Disable Force Mode,select Normal Mode no Compare Match ;Output
79
sbr r16,1<<CS00
80
cbr r16,1<<CS01
81
sbr r16,1<<CS02 ;Prescaler 1024
82
out TCCR0,r16
83
in r16,TIMSK
84
sbr r16,1<<TOIE0
85
out TIMSK,r16 ; Timer/Counter0 Overflow Interrupt Enable
86
sei ;Interrupts global freischalten
87
clt ;loescht T-Flag im SREG
88
89
90
91
hauptschleife:
92
in r16,GICR ;Interrupts (INT0/INT1) wieder aktivieren
93
sbr r16,1<<INT0
94
sbr r16,1<<INT1
95
out GICR, r16
96
97
call ueberlaufkontrolle
98
99
brts ausgabe1 ;falls das T-Flag gesetzt ist nach "ausgabe1" springen
100
101
cpi status,0x00 ;Statusabfrage
102
breq ausgabe1
103
cpi status,0x01
104
breq ausgabe2
105
cpi status,0x02
106
breq berechnen
107
108
jmp hauptschleife
109
110
111
berechnen:
112
set ;Setzt T-Flag, um dann in der "hauptschleife" das ;Ergenis auszugeben
113
mul zaehler1,zaehler2
114
mov resultat,r0
115
jmp ausres1
116
117
118
warten: ;für die Entprellung des Tasters --> wartet 90ms
119
cpi zehn_ms,0x09
120
breq hauptschleife
121
jmp warten
122
123
124
125
126
ausres1: ;Berrechnet den Wert für die Variable "zaehler1",um die die ;Zehnerstelle auf der 1. 7-Segmente-Anzeige ;auszugeben
127
mov r16,resultat
128
sub r16,zehner
129
tst r16 ;auf null testen
130
breq einererhoehen
131
brne zehnererhoehen
132
133
ausres2:
134
mov r16,resultat
135
add zehner,einer
136
sub r16,zehner
137
mov zaehler2,einer
138
tst r16
139
breq hauptschleife
140
brne einererhoehen
141
142
zehnererhoehen:
143
ldi r16,0x0A
144
add zehner,r16
145
inc zz
146
jmp ausres1
147
148
einererhoehen:
149
mov zaehler1,zz
150
inc einer
151
jmp ausres2
152
153
ausgabe1:
154
ldi zaehler2,0x00
155
push r16
156
push ZL
157
push ZH
158
159
ldi ZL,Low(zahlen<<1)
160
ldi ZH,High(zahlen<<1) ; Adresse Tabelle
161
clr r16 ; Null für Übertrag
162
add ZL,zaehler1 ; +Offset
163
adc ZH,r16 ; Übertrag berücksichtigen
164
lpm r16,Z ; Tabellenwert holen
165
out PORTA,r16 ; ausgeben
166
167
pop ZH
168
pop ZL
169
pop r16
170
171
brts ausgabe2
172
173
ldi zehn_ms,0x00 ;Zeitzähler auf 0 setzen
174
jmp warten
175
176
ausgabe2:
177
push r16
178
push ZL
179
push ZH
180
181
ldi ZL,Low(zahlen<<1)
182
ldi ZH,High(zahlen<<1) ; Adresse Tabelle
183
clr r16 ; Null für Übertrag
184
add ZL,zaehler2 ; +Offset
185
adc ZH,r16 ; Übertrag berücksichtigen
186
lpm r16,Z ; Tabellenwert holen
187
out PORTB,r16 ; ausgeben
188
189
pop ZH
190
pop ZL
191
pop r16
192
193
ldi zehn_ms,0x00
194
jmp warten
195
196
197
198
ueberlaufkontrolle:
199
in r16,GICR
200
cbr r16,1<<INT0
201
cbr r16,1<<INT1
202
out GICR, r16
203
204
ldi r16,0x05
205
mov uelreg,status
206
cp uelreg,r16
207
breq ueberlauf
208
209
ldi r16,0x0A
210
mov uelreg,zaehler1
211
cp uelreg,r16
212
breq ueberlauf
213
214
ldi r16,0x0A
215
mov uelreg,zaehler2
216
cp uelreg,r16
217
breq ueberlauf
218
219
ret
220
221
ueberlauf:
222
ldi uelreg,0x00
223
jmp hauptschleife
224
225
226
227
zahlen: ;Tabelle mit PORT-Masken für die Zahlen von 0-9
Hi
War aber nur eins am Anfang. Innerhalb des Programms wird T nur gesetzt,
Aber nicht wieder gelöscht.
Schwerwiegender:
Stack ist falsch initialisiert: Erst High-Byte dann Low-Byte
ueberlaufkontrolle:
in r16,GICR
cbr r16,1<<INT0
cbr r16,1<<INT1
....
cp uelreg,r16
breq ueberlauf !!!!!!!!!!!!!!
ret
ueberlauf:
ldi uelreg,0x00
jmp hauptschleife !!!!!!!!!!!!
Das geht nicht. Du kannst aus einem Unterprogramm nicht nicht wieder so
ins Programm springen.
MfG Spess
Hallo,
spess53 schrieb:
> Stack ist falsch initialisiert: Erst High-Byte dann Low-Byte
Ist beim Stackpointer egal, der wird intern nicht gelatcht.
Gruß aus berlin
Michael