Forum: Mikrocontroller und Digitale Elektronik cbi TIFR, 1 -> out of range


von Markus (Gast)


Lesenswert?

ich möchte im Timer Interrupt Flag Register mit dem Befehl "cbi TIFR"
ein Flag 0 setzen. Doch das löst nur die folgende Fehlermeldung aus:
warten2.asm(233): error: Operand 1 out of range: 0x38
Woran mag das liegen? Das TIFR ist doch auch ein I/O-Register, das mit
cbi, sbi anzusprechen sein müsste?!? (zumindest funktionieren die
Befehle "in" und "out" auf dem Register)

von A.K. (Gast)


Lesenswert?

sbi/cbi: 0..31
in/out: 0..63.

von Markus (Gast)


Lesenswert?

das heisst wohl, dass sbi/cbi nur auf die register $0 bis $31 anzuwenden
sind, oder?
gibt es dazu einen eleganteren Umweg (am besten mit nur 1 Befehl)?

von A.K. (Gast)


Lesenswert?

0..31 = 0x00..0x1F
Ersatz: IN - ANDI/ORI - OUT

von Markus (Gast)


Lesenswert?

das hat aber glaub ich eine (zwar sehr kleine) unzuverlässigkeit. wenn
ein flag nach dem IN befehl gesetzt wird, überschreib ich nachher mit
out diese flag, deswegen hätte ich gerne das ganze in einem befehl
gehabt

von Philipp B. (philipp_burch)


Lesenswert?

Das ist wohl wahr, aber erstens kann sowas ja nur in einem Interrupt
passieren und zweitens ist die Wahrscheinlichkeit, dass der genau dort
feuert äusserst gering. Wenn du ganz sicher sein willst, kannst du ja
immer noch die Ints kurzzeitig ausschalten (cli, in, andi/ori, out,
sei).

von A.K. (Gast)


Lesenswert?


von Rolf Magnus (Gast)


Lesenswert?

> das hat aber glaub ich eine (zwar sehr kleine) unzuverlässigkeit.
> wenn ein flag nach dem IN befehl gesetzt wird, überschreib ich
> nachher mit out diese flag, deswegen hätte ich gerne das ganze in
> einem befehl gehabt

Wenn du den ausführst, nachdem das Flag gesetzt wurde, überschreibst
du's doch auch.

von johnny.m (Gast)


Lesenswert?

Wenn Du in einem Register, das nur Interrupt-Flags enthält (TIFR,
GIFR...) ein Bit löschen willst (und das ginge sowieso nicht mit cbi,
selbst dann, wenn das Register im bitadressierbaren Bereich läge, da ein
Interrupt-Flag gelöscht wird, indem man eine eins hineinschreibt),
dann schreib einfach die Bitmaske, in der die zu löschenden Bits '1'
sind, mit out in das Register! Also wenn Du z.B. das OCF0 löschen
willst, dann einfach mit
ldi r16, (1 << OCF0)
out TIFR, r16
Da das Schreiben einer '0' sowieso keinen Effekt hat, funktioniert
das ganz hervorragend. Und in solchen Fällen: Finger weg von 'in ->
ori -> out'! Damit löschst Du alle Flags im Register, die zum
Zeitpunkt des Einlesens (in) gesetzt waren! Immer eine direkte
Zuweisung benutzen. Das gilt auch in C (also kein '|=' sondern ein
'=').

Im Datenblatt der AVRs steht übrigens auch noch, dass sbi und cbi
alle Bits im betreffenden Register betreffen! Wenn Du in einem
Register, das bitadressierbar ist und das gleichzeitig Interrupt-Flags
enthält (also z.B. ADCSR(A)) ein Bit mit sbi setzt, löschst Du
gleichzeitig alle Interrupt-Flags in diesem Register (also im Beispiel
das ADIF)!

von johnny.m (Gast)


Lesenswert?

Ach, übrigens: Die Information über sbi und cbi steht in den
AVR-Datenblättern als Fußnote unter dem Register Summary. Ich hab das
damals auch eher zufällig entdeckt. Sonst habe ich diese Information
nirgends gefunden, auch nicht im Instruction Set Manual (wo sie imho
eigentlich hingehört)...

Die generellen Infos zum Löschen von Interrupt Flags gibts übrigens
auch in der AVR Checkliste auf dieser Seite.

von A.K. (Gast)


Lesenswert?

Aus dem Instruction Set Manual, zu CBI:

"Clears a specified bit in an I/O Register. This instruction operates
on the lower 32 I/O Registers &#8211; addresses 0-31."

von johnny.m (Gast)


Lesenswert?

Richtig, aber die Zusatzinfo, dass cbi und sbi alle Interrupt Flags im
betroffenen Register löschen steht anscheinend nur im Datenblatt...

von A.K. (Gast)


Lesenswert?

Das steht da nicht drin, weil es wirklich rein garnichts mit diesen
Befehlen zu tun hat. Das ist eine Eigenschaft des Registers und ist
völlig unabhängig davon, mit welchen Befehlen man das macht.

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.