Forum: Mikrocontroller und Digitale Elektronik Register verändern sich von Geisterhand


von Robert V. (malso)


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

von (prx) A. K. (prx)


Lesenswert?

Das Statusregister wird bei einem Interrupt nicht implizit gesichert.

von Michael U. (amiga)


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

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Robert V. schrieb:
> Ich benutze ASM und habe das Problem, das die
> REGISTER,  meinetwegen r19 oder r24, nach einem Interrupt Aufruf, ihre
> Werte ändern.

Wenn du im Interrupt-Handler R19 veränderst, dann könnte es tatsächlich 
vorkommen, dass sich R19 wirklich ändert. ;-)

von Peter D. (peda)


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.

von Bitwurschtler (Gast)


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".

von Peter D. (peda)


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.

von Jörn P. (jonnyp)


Lesenswert?

Peter D. schrieb:
> In Assembler muß man sich eben um jeden Pipfax selber kümmern.

Du hast früher aber auch (gerne ???) Assembler programmiert ;-)

von Eric B. (beric)


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.

von Robert V. (malso)


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

von (prx) A. K. (prx)


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.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

1
 ldi r17,0x00          ;Alles Ausgänge  PD PB
2
 out DDRB,r17
3
 out DDRD,r17

?
Alles Eingänge!

von Sascha W. (sascha-w)


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

von Robert V. (malso)


Lesenswert?

OK das war schlampig von mir und erklärt einiges. Ich werde das gleich 
korregieren.

von Staubfänger (Gast)


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.

von Jobst M. (jobstens-de)


Lesenswert?

Vor allem führt auch kein Weg daran vorbei, das Statusregister zu 
sichern, wenn im Hauptprogramm damit eine Entscheidung getroffen wird.
Wurde ja auch schon erwähnt.


Gruß

Jobst

von Robert V. (malso)


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

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> was keinen Unterschied macht...
Es wurden vorher mit 'out PORT...' die internen pull-up-Widerstände ein- 
bzw. ausgeschaltet. Wenn das dem Schrittmotortreiber reicht, okay.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Robert V. schrieb:
> Des weiteren ist meine Flanke nicht steil genug.

Dafür hat der Tiny2313 den analogen Komparator, dafür solltest du 
allerdings PB0 und PB1 nicht anderweitig benutzen.

von Robert V. (malso)


Lesenswert?

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.

MfG

von Sebastian S. (amateur)


Lesenswert?

Da Du definitiv sowohl im Hauptprogramm am Status-Register 
herumfummelst, als auch in den Unterbrechungsroutinen, kann ein 
"Missverständnis" als sicher angenommen werden.
Natürlich bleibt, wie immer, die Frage offen: Wann?

von Peter D. (peda)


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.

von Michael U. (amiga)


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

: Bearbeitet durch User
von Rächdschraiplehra (Gast)


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

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.