Register verändern sich von Geisterhand

OP #4571182
Lesenswert?

Hallo,

Ich habe mal wieder ein Problem, was ich scheinbar nicht selbst gelöst 
kriege. Ich bin dabei mir die Drehzahl eines Drehtellers zu ermitteln 
(Attiny2313 mit 12mhz-quarz). Der Drehteller hat eine 
Schwarz/Weiss-Teilung, welche ich mittels Fototransistor/LED abtaste 
(INT0). Während dessen Zähle ich die Abstände der 
Impulse(TIMER0-Overflow). Ich benutze ASM und habe das Problem, das die 
REGISTER,  meinetwegen r19 oder r24, nach einem Interrupt Aufruf, ihre 
Werte ändern. Ich kann sie also nicht als Umgebungsvariablen nutzen. 
Wenn ich alles mittels sts/lds im SRAM erledige, geht es "soweit" in 
Ordnung. Aber ich vermiese mir das ganze Wochenende mit Fehlersuche und 
dann finde ich keine Erklärung.
Das Programm ist ursprünglich komplexer und ich musste es, der 
Fehlersuchehalber, soweit herunterkürzen. Ein Schrittmotor sollte mir 
das tachomäßig anzeigen. Es geht mir hauptsächlich um den Fakt, das sich 
die Register ändern. Schon mal Danke für diejenigen die sich das 
durchlesen...Muss jetzt zur Arbeit..


1
.include "2313.inc"
2
rjmp START
3
.org INT0addr
4
rjmp IMPULS
5

6
.org OVF0addr
7
rjmp TIMER
8
reti
9

10

11
.cseg
12
SCHRITTE:
13
.db 0b00001010,0b00001000,0b00001001,0b00000001,0b00000101,0b00000100,0b00000110,0b00000010
14

15

16
START:
17

18
 ldi r16,0xDF
19
 out SPL,r16
20

21
 ldi r16,(1<<ISC01) | (1<<ISC00)
22
 ldi r16,0b00000011
23
 out MCUCR,r16
24
 ldi r16,(1<<INT0)
25
 out GIMSK, r16
26

27
 ldi r16,0b00000011
28
 out TCCR0,r16
29
 ldi r16,0b00000010
30
 out TIMSK,r16
31
 
32

33
 ldi r22,0x00
34
 ldi r23,0x01
35

36
 sts SOLLZEIT,r22
37
 sts SOLLZEIT+1,r23 
38
 ldi r23,0
39
 sts ZEIGER,r23
40
 ldi r23,5
41
 sts ZEIGER+1,r23
42

43
 ldi r17,0x00
44
 out DDRB,r17
45
 out DDRD,r17
46
 out PORTB,r17
47

48
 ldi r26,1
49
 
50
  
51
sei
52

53
 
54
LOOP: 
55
 dec r29
56
 brne LOOP
57
 rcall ANZEIGE
58

59
rjmp LOOP
60

61

62

63
TIMER:
64

65
 lds r19,ZEIT            ;WARUM KANN ICH  R19 NICHT SO NEHMEN
66
 inc r19
67
 brne CW
68
 inc r20
69
 brne CW
70
 dec r20
71
 
72

73
 CW: 
74
 sts ZEIT,r19
75
reti
76

77

78
IMPULS:
79

80
  
81
 lds r22, ZEIT
82
 cpi r22,71
83
 brlo IW
84
 ldi r22,70
85
 IW:
86
 cpi r22,4
87
 brsh IW2
88
 ldi r22,5
89
 IW2:
90

91
 sts ZEIGER+1,r22
92
 ldi r19,0
93
 ldi r20,0  
94
reti
95

96

97

98

99
ANZEIGE:
100
 
101
 lds r24,ZEIGER+1
102
 
103
 lds r25,ZEIGER
104
 cp r25,r24
105
 brsh ZUWEIT
106

107
 ZUNAH:
108
 inc r25
109
 cpi r25,71
110
 brlo SZN
111
 ldi r25,70
112
 SZN:
113
 sts ZEIGER,r25
114
 rcall PLUSY
115
ret
116

117

118
 ZUWEIT:
119
 cp r24,r25
120
 breq GLEICH
121

122
 dec r25
123
 cpi r25,01
124
 brsh SZW
125
 ldi r25,2
126
 SZW:
127
 sts ZEIGER,r25
128
 rcall MINUSY
129
 ret
130

131
 GLEICH:
132
  sts ZEIGER,r24
133
ret
134

135

136
WARTEY:
137
 push r22
138
 push r23
139
 ldi r22,0x20
140
 ldi r23,0xff
141
 WAITCHECKY_1:
142
  dec r23
143
 brne WAITCHECKY_1
144
  dec r22
145
 brne WAITCHECKY_1
146
 pop r23
147
 pop r22
148
ret
149

150

151

152

153

154
PLUSY:
155
 inc r17
156
 cpi r17,8
157
 brne PLUS_ENDY
158
 ldi r17,0
159
 PLUS_ENDY:
160
 ldi ZL,low(SCHRITTE*2)
161
 ldi ZH,high(SCHRITTE*2)
162
 add ZL,r17
163

164
 lpm 
165
 mov r18,r0
166
 mov r16,r18
167
 andi r16,0b00000011
168
 lsl r18
169
 andi r18,0b00011000
170

171
 or r18,r16
172
 out PORTD,r18
173
 rcall WARTEY
174
ret
175

176

177

178
MINUSY:
179
 dec r17
180
 cpi r17,0xFF
181
 brne MINUS_ENDY
182
 ldi r17,7
183
 MINUS_ENDY:
184
 ldi ZL,low(SCHRITTE*2)
185
 ldi ZH,high(SCHRITTE*2)
186
 add ZL,r17
187
 lpm 
188
 mov r18,r0
189
 mov r16,r18
190
 andi r16,0b00000011
191
 lsl r18
192
 andi r18,0b00011000
193

194
 or r18,r16
195
 out PORTD,r18 
196
rcall WARTEY
197
ret
198

199

200

201
.dseg
202
.byte 10
203
SOLLZEIT: .byte 2
204
ZEIGER: .byte 2
205
ZEIT: .byte 2
#4571191
Lesenswert?

Hallo,

wenn Du die Register in einer Interruptroutine benutzt werden sie 
natürlich ihren Wert entsprechend ändern.
Wenn sie im Hauptprogramm auch genutzt werden, mußt sie eben in der ISR 
mit push / pop sichern.

PS: ich wünsche Dir viel Vergnügen, falls Du in 2 Jahren nochmal in Dein 
Programm schaust: keine Kommentare, keine sinnvollen Namen per 
Register-Defines usw. usw.
Das geht auch alles in ASM.

Gruß aus Berlin
Michael
#4571516
Lesenswert?

Robert V. schrieb:
> das die
> REGISTER,  meinetwegen r19 oder r24, nach einem Interrupt Aufruf, ihre
> Werte ändern.

Wenn Du im Interrupt Register benutzt und nicht sicherst, sollte klar 
sein, daß im Main Unsinn passiert.
In Assembler muß man sich eben um jeden Pipfax selber kümmern.
Nur eine Programmiersprache sichert benutzte Register automatisch.
Gast #4571533
Lesenswert?

Peter D. schrieb:
> In Assembler muß man sich eben um jeden Pipfax selber kümmern.
> Nur eine Programmiersprache sichert benutzte Register automatisch.

Nicht nur benutzte Register, sondern auch unbenutzte, da eine 
Prog-sprache meist nicht Überblick eines Assembler-Programmierer hat.

Zwar können Willensstarke auch einem C-Compiler ihren Willen aufzwingen, 
aber das ist dann auch wieder "Pipfax um den man sich selbst kümmern 
muss, damit es perfekt passt".
#4571555
Lesenswert?

Bitwurschtler schrieb:
> Nicht nur benutzte Register, sondern auch unbenutzte, da eine
> Prog-sprache meist nicht Überblick eines Assembler-Programmierer hat.

Eine Programmiersprache behält immer den Überblick, wo ihn der 
Assembler-Frickler schon längst verloren hat. Ich möchte jedenfalls 
keine 64kB in Assembler schreiben.

Bitwurschtler schrieb:
> Zwar können Willensstarke auch einem C-Compiler ihren Willen aufzwingen

Willensstärke ist völlig unnötig, einfach Unterfunktionen, die in 
Interrupts aufgerufen werden, als Inline definieren.

Es gibt bei einigen Compilern aber auch globale Optimierung, d.h. sie 
merken sich die Registernutzung von Unterfunktionen und nutzen 
Register-Renaming.
#4571849
Lesenswert?

Peter D. schrieb:
> Bitwurschtler schrieb:
>> Nicht nur benutzte Register, sondern auch unbenutzte, da eine
>> Prog-sprache meist nicht Überblick eines Assembler-Programmierer hat.
>
> Eine Programmiersprache behält immer den Überblick, wo ihn der
> Assembler-Frickler schon längst verloren hat.

Assembler ist aber auch eine Programmiersprache. Es ist nicht so sehr 
die Sprache die den Überblick behält, sondern der Programmierer. Und der 
kann das in Assembler genau so gut oder schlecht, wie in jeder beliebige 
andere Programmiersprache auch.
OP #4572179
Lesenswert?

OK, der Programmiercode den ich gelistet habe scheint zu undurchsichtig. 
So habe ich das Programm noch etwas gekürzt und kommentiert. Und 
Assembler sieht, meiner Meinung nach, einfach besser aus. So 
funktioniert das Prog schon ein wenig in die Richtung in die ich wollte. 
Ich glaube eines meiner Problem liegt auch an der mangelnden 
Flankensteilheit.
Die Register besitzen immer nur eine Bedeutung! Sie sollen als 
Umgebungsvariablen dienen, was leider nicht funktioniert.




1
.include "2313.inc"
2
rjmp START
3
.org INT0addr
4
rjmp IMPULS
5

6
.org OVF0addr
7
rjmp TIMER
8
reti
9

10

11

12
.cseg
13
SCHRITTE:                     ;Hier ist die Bitfolge, welche der schrittmotor benötigt
14
.db 0b00001010,0b00001000,0b00001001,0b00000001,0b00000101,0b00000100,0b00000110,0b00000010
15

16

17
START:
18

19
          ;Stack festlegen
20
 ldi r16,0xDF
21
 out SPL,r16        ;INT0 ->  IMPULS
22
 ldi r16,(1<<ISC01) | (1<<ISC00)
23
 ldi r16,0b00000011        ;auf steigende Flanke
24
 out MCUCR,r16
25
 ldi r16,(1<<INT0)
26
 out GIMSK, r16
27
            ;Vorteiler 8 
28
 ldi r16,0b00000010      
29
 out TCCR0,r16
30
 ldi r16,0b00000010
31
 out TIMSK,r16
32

33
             ;Speicherzelle 1  
34
 ldi r23,0
35
 sts ZEIGERIST,r23
36
 ldi r23,5
37
 sts ZEIGERSOLL,r23
38

39
 ldi r17,0x00          ;Alles Ausgänge  PD PB
40
 out DDRB,r17
41
 out DDRD,r17
42
 out PORTB,r17          ; PORTB Auf 0
43

44
          
45
 
46
  ldi r29,100          ; Tachonadel wird auf 0 Gesetzt (Bleibt am Anschlag hängen).
47
  ZEIGERNULL:
48
  rcall MINUSY
49
  dec r29
50

51
  brne ZEIGERNULL
52
  
53
sei
54

55
 
56
LOOP: 
57
 dec r29      ;Hauptroutine mit r29 als Zähler, damit darauffolgender 
58
 brne LOOP      ;RCALL Befehl nicht zu oft ausgeführt wird
59
 rcall ANZEIGE      ;Gehe in Anzeige-Routine
60

61
rjmp LOOP
62

63

64

65
TIMER:
66

67
 lds r19,ZEIT      ;Ich kann mir nicht anders helfen
68
 inc r19      ;16 Bit zähler, von dem , dank TIMER-Vorteiler von 8 nur 
69
 brne CW      ;die ersten 8 Bit gebraucht werden bei einer Tellerumdehung 
70
 inc r20      ;von 1 U/MIN und 132 Impulsen pro Sekunde.
71
 brne CW      ;Wenn zu selten IMPULS-INT0, dann fang nicht vorne an, sondern bleib 
72
 dec r20      ;Höchstwert (Drehteller = Superlangsam)
73
 
74

75
 CW: 
76
 sts ZEIT,r19      ;Wieder die Hilflosigkeit, weil er r19 einfach Platt macht
77
reti
78

79

80

81

82

83

84
IMPULS:        ;die Flankenroutine
85
  
86
 lds r22, ZEIT      ;Dilemma
87
 cpi r22,71      ;höchstwert der Anzeige überschritten
88
 brlo IW
89
 ldi r22,70      ;dann auf den Höchstwert setzen
90
 IW:
91
 cpi r22,4      ;Das selbe mit Niedrigstwert
92
 brsh IW2      ;wurde aus Fehlersuchgründen hochgesetzt
93
 ldi r22,5
94
 IW2:
95
 sts ZEIGERSOLL,r22    ;das Ergebnis kommt in die Zeigersoll-Speicherzelle
96
 ldi r19,0      ;16 Bit Zähler wird genullt, weil ja der nächste Impuls wieder beginnt
97
 sts ZEIT,r19      
98
 sts ZEIT+1,r19      
99
reti
100

101

102

103

104

105

106
ANZEIGE:         ;Vergleicht den alten mit dem neuen Zeigerstand (Ist-Soll)
107
 
108
 lds r24,ZEIGERSOLL    ;lädt die Sollstellung des Zeigers in r24
109
 
110
 lds r25,ZEIGERIST     ;lädt die Iststellung in r25
111
 cp r25,r24      ;ist die Ist-Stellung zu hoch oder gleich, dann springe !
112
 brsh ZUWEIT
113

114
 ZUNAH:        ;wenn nicht, dann ist der Zeiger zu niedrig
115

116
 inc r25      ;Zeiger Istwert erhöhen
117
 cpi r25,71      ;Wenn zu hoch, dann in die Schranken weisen
118
 brlo SZW
119
 ldi r25,70
120
 SZW:
121

122

123
 sts ZEIGERIST,r25    ;neuen Wert in Zeiger-Ist speichern
124
 rcall PLUSY      ;Schrittmotor um einen Schritt nach rechts !
125
ret        ;und zurück in die LOOP Routine
126

127

128
 ZUWEIT:      ;Wenn Istwert(Zeiger) höher oder gleich wie Soll-Wert
129

130
 cp r24,r25      ;Wenn Soll- und Istwert gleich, dann Routine verlassen
131
 breq GLEICH      ;da Anzeige gleich bleibt. Wenn nicht dann weiter...
132
      
133

134
 dec r25      ;Zeiger um einen Wert verringern
135
 cpi r25,0      ;Aber aufpassen das er nicht unter Null wird! 
136
 brsh SZN
137
 ldi r25,1      
138
 SZN:
139

140
 sts ZEIGERIST,r25    ;neuer Sollzeigerwert ins Register
141
 rcall MINUSY      ;Schrittmotor nach links
142

143
 GLEICH:
144
ret
145

146

147
WARTEY:        ;Verzögerungsroutine für Schrittmotor.
148
 push r22
149
 push r23
150
 ldi r22,0x20
151
 ldi r23,0xff
152
 WAITCHECKY_1:
153
  dec r23
154
 brne WAITCHECKY_1
155
  dec r22
156
 brne WAITCHECKY_1
157
 pop r23
158
 pop r22
159
ret
160

161

162

163

164

165
PLUSY:        ;Schrittmotor nach rechts
166
 inc r17
167
 cpi r17,8      ;r17 ist UMGEBUNGSVARIABLE
168
 brne PLUS_ENDY
169
 ldi r17,0
170
 PLUS_ENDY:
171
 ldi ZL,low(SCHRITTE*2)    ;hier sind die Schritt-Bits gespeichert
172
 ldi ZH,high(SCHRITTE*2)
173
 add ZL,r17
174

175
 lpm 
176
 mov r18,r0
177
 mov r16,r18
178
 andi r16,0b00000011
179
 lsl r18
180
 andi r18,0b00011000
181

182
 or r18,r16
183
 out PORTD,r18
184
 rcall WARTEY
185
ret
186

187

188

189
MINUSY:        ;das selbe wie bei PLUSY
190
 dec r17      ;r17 ist UMGEBUNGSVARIABLE
191
 cpi r17,0xFF
192
 brne MINUS_ENDY
193
 ldi r17,7
194
 MINUS_ENDY:
195
 ldi ZL,low(SCHRITTE*2)
196
 ldi ZH,high(SCHRITTE*2)
197
 add ZL,r17
198
 lpm 
199
 mov r18,r0
200
 mov r16,r18
201
 andi r16,0b00000011
202
 lsl r18
203
 andi r18,0b00011000
204

205
 or r18,r16
206
 out PORTD,r18 
207
rcall WARTEY
208
ret
209

210

211

212
.dseg
213
.byte 10
214
SOLLZEIT: .byte 2
215
ZEIGERSOLL: .byte 1
216
ZEIGERIST:  .byte 1
217
ZEIT: .byte 2
#4572190
Lesenswert?

Dir ist bekannt, was ein Status-Register ist, was beispielsweise das 
"Zero" Flag ist? Deine Hauptschleife ist von dessen Zustand abhängig, 
die darin aufgerufene Anzeigeroutine auch. Deine Interrupt-Handler 
verändern jedoch dieses Flag, ohne das Statusregister mit dem Z Flag 
darin zu sichern. Das geht in die Hose.
#4572210
Lesenswert?

Robert V. schrieb:
> OK, der Programmiercode den ich gelistet habe scheint zu undurchsichtig.
> So habe ich das Programm noch etwas gekürzt und kommentiert. Und
> Assembler sieht, meiner Meinung nach, einfach besser aus. So
> funktioniert das Prog schon ein wenig in die Richtung in die ich wollte.
> Ich glaube eines meiner Problem liegt auch an der mangelnden
> Flankensteilheit.
> Die Register besitzen immer nur eine Bedeutung! Sie sollen als
> Umgebungsvariablen dienen, was leider nicht funktioniert.
Tun sie NICHT,
R19 benutzt du in beiden Int-Routinen, da brauchst du dich nicht wundern 
das sich der Zustand ändert
R22 verwendest du auch in WARTY

Und wie schon erwäht du kannst den Registern ruhig Namen geben - dann 
weiß man wenigstens für was die da sind.

Sascha
Gast #4572230
Lesenswert?

Robert V. schrieb:
> Die Register besitzen immer nur eine Bedeutung! Sie sollen als
> Umgebungsvariablen dienen, was leider nicht funktioniert.

Vermutlich liegt hier der wichtige Punkt in Deinem Verständnis.
Ich weiss ja nicht, zu welchem System Du da die Analogie herstellst, 
aber es ist vielleicht hilfreich, zumindest vorerst, Register nicht 
als Umgebungsvariablen zu betrachten.


Wenn Du an irgendeiner Stelle im Code, ein Register (R0-R31) mit einem 
bestimmten Wert lädst, dann behält dieses Register, egal was geschieht 
diesen Wert, solange bis sein Inhalt wieder geändert wird.

"Egal was geschieht" gilt insbesondere auch für Interrupt-Routinen. Das 
ist hier sinngemäß schon einige Male gesagt worden, aber vielleicht 
nicht deutlich genug erklärt.

Betrachte das mal einen Moment lang als nützlich: Wenn Du in einer 
Interrupt-Routine ein Register mit einem Wert lädst, z.B. mit dem 
zuletzt vom UART empfangenen Byte aus UDR, dann bleibt der da, auch wenn 
die ISR verlassen wurde (mit IRET). Das Hauptprogramm kann also dieses 
empfangende Byte aus dem Register lesen, weil es immer noch darin ist 
. Gut, oder?

Umgekehrt geht das natürlich auch; vom Hauptprogramm zur ISR.

ABER: Wenn Du im Hauptprogramm in dem Register einen wichtigen Wert 
hast, der erhalten werden soll UND Du in der ISR, das selbe Register 
anderweitig benutzt, dann MUSST Du das Register am Anfang der ISR mit 
push auf den Stack sichern (mit STI oder so im RAM speichern geht 
prinzipiell auch) und es vor dem verlassen der ISR mit pop wieder 
herstellen.
Daran führt kein Weg vorbei.
OP #4572284
Lesenswert?

danke habe die Register+Statusregister der Interruptroutinen gesichert, 
habe diesen Fakt wirklich nicht bedacht.
Ich habe DDRD jetzt mit 0b11111011 gesetzt (das ist mir megapeinlich), 
was keinen Unterschied macht..... Schrittmotor welcher an PD0,PD1,..PD3 
und PD4 liegt funktionierte vorher auch.

Jetzt scheint alles zu funktionieren.
Jetzt kann ich den Prescaler verringern um die Genauigkeit zu erhöhen 
und einen durchschnitt zu bilden.
Des weiteren ist meine Flanke nicht steil genug. Es handelt sich um ein 
Zahnkranz, wobei die Stirnflächen der Zähne mit weißer Farbe markiert 
worden. Ich beleuchte sie mit einer Weißen LED nebenan der 
Fototransistor an Int0. Das krieg ich schon hin.

1000 Dank an euch
#4572729
Lesenswert?

Robert V. schrieb:
> Kaum zu
> glauben, das ich seit 4...5 Jahren AVR's für meine Bastelprojekte
> benutze.

Und Du hast bisher noch nie Interrupts benutzt?
Das saugt man doch schon fast mit der Muttermilch auf, daß alles, was 
man im Interrupt zerstört, auch gesichert werden muß.

Es gibt natürlich auch die Möglichkeit, sich einige der 32 Register 
exklusiv für Interrupts zu reservieren, d.h. die sind dann für das Main 
strengstens tabu. Man sollte dann aber den Registern Namen geben, damit 
man nicht den Überblick verliert.
#4572927
Lesenswert?

Hallo,
1
TIMER:
2

3
 lds r19,ZEIT      ;Ich kann mir nicht anders helfen
4
 inc r19      ;16 Bit zähler, von dem , dank TIMER-Vorteiler von 8 nur 
5
 brne CW      ;die ersten 8 Bit gebraucht werden bei einer Tellerumdehung 
6
 inc r20      ;von 1 U/MIN und 132 Impulsen pro Sekunde.
7
 brne CW      ;Wenn zu selten IMPULS-INT0, dann fang nicht vorne an, sondern bleib 
8
 dec r20      ;Höchstwert (Drehteller = Superlangsam)
9
 
10

11
 CW: 
12
 sts ZEIT,r19      ;Wieder die Hilflosigkeit, weil er r19 einfach Platt macht
13
reti

meine Grundregel:
in einer ISR werden alle dort benutzten Register gerettet.
1
 push r19          ;bietet sich hier an, weil es sowieso gleich genutzt wird.
2
 in r19,SREG
3
 push r19          ; Statusregister retten
4
 push r20
5
...
6
 pop r20
7
 pop r19
8
 out SREG,r19
9
 pop r19
10
 reti

 Wenn jetzt r20 eine "globale Variable" sein soll, die in der IRQ 
geändert werden soll, sollte das auch einen Namen haben:

.def U_MIN = r20
1
 push r19          ;bietet sich hier an, weil es sowieso gleich genutzt wird.
2
 in r19,SREG
3
 push r19          ; Statusregister retten
4

5
 lds r19,ZEIT      ;Ich kann mir nicht anders helfen
6
 inc r19      ;16 Bit zähler, von dem , dank TIMER-Vorteiler von 8 nur 
7
 brne CW      ;die ersten 8 Bit gebraucht werden bei einer Tellerumdehung 
8
 inc U_MIN      ;von 1 U/MIN und 132 Impulsen pro Sekunde.
9
 brne CW      ;Wenn zu selten IMPULS-INT0, dann fang nicht vorne an, sondern bleib 
10
 dec U_MIN      ;Höchstwert (Drehteller = Superlangsam)
11
 
12

13
 CW: 
14
 sts ZEIT,r19      ;Wieder die Hilflosigkeit, weil er r19 einfach Platt macht
15

16
 pop r19
17
 out SREG,r19
18
 pop r19
19
 reti

Meist gibt es bei mir 2..4 Temporäre Register, die bekommen auch Namen, 
siehtt dann meist so aus:
1
;--- lower Register -----------------------------------------------
2

3
.def  MUL_LOW    = r0
4
.def  MUL_HIGH  = r1
5

6
.def  ZERO    = r2            ; 0 für Berechnungen
7

8
;--- higher Register ----------------------------------------------
9

10
.def  FLAGS    = r21            ; allgemeines Flagregister
11

12
.def    TEMP_0      = r22            ; 4 temporäre  8Bit-Register
13
.def    TEMP_1      = r23
14
.def    TEMP_2      = r24
15
.def    TEMP_3      = r25
16

17
; r26/r27 - X, r28/r29 - Y, r30/r31 - Z

Dann würde Dein Code etwa so aussehen:
1
; irgendwo an Anfang
2
.def    TEMP_0      = r22            ; temporäres  8Bit-Register
3
.def    U_MIN       = r20            ; U/min  
4

5
....
6

7
TIMER:
8
 push TEMP_0                         ;bietet sich hier an, weil es sowieso gleich genutzt wird.
9
 in   TEMP_0, SREG
10
 push TEMP_0                         ; Statusregister retten
11

12
 lds  TEMP_0, ZEIT                   ;Ich kann mir nicht anders helfen
13
 inc  TEMP_0                         ;16 Bit zähler, von dem , dank TIMER-Vorteiler von 8 nur 
14
 brne CW                             ;die ersten 8 Bit gebraucht werden bei einer Tellerumdehung 
15
 inc  U_MIN                          ;von 1 U/MIN und 132 Impulsen pro Sekunde.
16
 brne CW                             ;Wenn zu selten IMPULS-INT0, dann fang nicht vorne an, sondern bleib 
17
 dec  U_MIN                          ;Höchstwert (Drehteller = Superlangsam)
18
 
19

20
 CW: 
21
 sts  ZEIT,TEMP_0                    ;Wieder die Hilflosigkeit, weil er r19 einfach Platt macht
22

23

24
 pop  TEMP_0
25
 out  SREG,TEMP_0
26
 pop  TEMP_0
27
 reti

Wird sicher jeder etwas anders machen, aber auch ASM kann lesbar sein.

Gruß aus Berlin
Michael
Gast #4572939
Lesenswert?

Robert V. schrieb:
> Danke Leute ihr habt mir viele Arbeitsstunden erspart. Und mit dem
> analogen Komperator muss ich mich erstmal auseinander setzten. Kaum zu
> glauben, das ich seit 4...5 Jahren AVR's für meine Bastelprojekte
> benutze.

Komperator -->  Komparator

AVR's  --->  AVRs   (www.deppenapostroph.info)

Robert V. schrieb:
> Ich werde das gleich *korregieren*

korregieren -->  korrigieren

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren