mikrocontroller.net

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


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sbi/cbi: 0..31
in/out: 0..63.

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)?

Autor: A.K. (Gast)
Datum:

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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Markus: Yep, das ist eine Schwäche der AVRs.
http://www.mikrocontroller.net/articles/Interrupt#...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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."

Autor: johnny.m (Gast)
Datum:

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

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.