Schönen guten Tach,
ich will das Timer/Counter0 Overflow Flag TOV0 im Register TIFR setzen
(ATTiny 2313 mit AVR Studio). Wie geht das ? SBI TIFR,1 klappt nicht,
Compiler meckert: "Operand 1 out of range" .
Danke für jeden Ratschlag.
Tilman
> ich will das Timer/Counter0 Overflow Flag TOV0 im Register TIFR> setzen (ATTiny 2313 mit AVR Studio). Wie geht das ?
Gar nicht. Man kann es nur löschen. Das tut man allerdings
verwirrenderweise, indem man eine 1 reinschreibt.
> SBI TIFR,1 klappt nicht, Compiler meckert: "Operand 1 out of> range" .
Da hat er recht :)
TIFR ist ein Register, das sich nicht mit sbi ansprechen lässt. Also
so:
in r16, TIFR
ori r16, (1 << TOV0)
out TIFR, r16
Bitte mal die Suche bemühen. Beim TINY2313 liegen viele Peripherie
Register außerhalb des mit SBI/CBI adressierbaren Bereiches.
Auch kann ein Interrupt-Flag nicht manuell gesetzt werden. Nur das
Zurücksetzen indem eine "1" zurückgeschrieben wird ist möglich.
Ja ich bin ja vor 2 Wochen auch in die AVR programmierung
eingestiegen... und das man mit ldi nicht r0 bis r31 sondern nur r16
bis r31 ansprechen kann ist genauso unlogisch wie die sache mit
verscheiden Registern welche sich per sbi und cbi nicht ansprechen
lassen.
Hat jemand eine Ahnung warum das so ist? Oder ist das einfach nur eine
dumme eigenheit der AVRs.
Ich meine man, kommt zwar auch so zum Ziel, aber oft benötigt man dann
ein weiteren Befehl (mehr Zeit) oder ein zusätzliches Register welches
man im Notfall sogar noch mit push und pop vorher retten muß (noch mehr
Zeit, mehr Stackverbrauch)
Ich weiss auch nicht, weshalb man die meisten Befehle nur bis
einschliesslich r31 verwenden kann, Bandit. Frag die Experten (Rolf,
MMerten). Ich bin hier leider nicht tief genug in der Materie.
Weil alle Befehle nur 2 Byte lang sind.
Im Gegensatz zu anderen Controllern ist das unglaublich komprimierter
Opcode, da es ja sehr viele komfortable Befehle gibt (im Gegensatz
wiederum zum PIC, wo User mit sehr wenigen Befehlen in Assembler
auskommen muß).
Wenn du dir die ganzen Opcodes ansiehst (also die Hex-Zahlen, die den
Assembler Vebfehlen entsprechen), dann siehst, du, dass bei manchem
Befehlen quasi der Befehlsname lang ist, dann bleiben von den 16bit
evtl. nur noch 5 Bit für den Paramter übrig, also nur für die ersten 32
Register.
Andere Befehle haben sehr kurze "Namen", dann bleibt mehr Platz für
die Parameter.
Es kann aber eben nicht beliebig viele Kurz-namige Befehle geben, weil
es dann zu wenige am Ende wären.
Das ganze ist sehr durchdacht und keine schlichte Nebenwirkung
irgendwelcher "Modernisierungsmaßnahmen", wie bei vielen aufgebohrten
alten Controller-Kernen.
jörn
Ja stimmt, das ergibt dann auch einen Sinn :)
Ich habe mich bis jetzt nur einfach totgeärgert wenn mal wieder so ein
Fall dran war.
Doch hätte ich dann wohl noch einen äquivalenten Befehl für die
restlichen Register eingebracht. Aber gut das überlasse ich mal den
Profis von Atmel :)
Aber du hast recht, ich habe vorher nur mit PIC16Fxxx gearbeitet und da
war mir der Befehlssatz etwas zu dürftig... beim PIC18 soll es ja etwas
besser sein. Aber der AVR lässt sich schon schöner programmieren.
Naja man nimmt einfach die ersten Regsiter für alle Sachen die nicht soo
ft oder sogar garnicht mit Imideate werden benötigt werden.
Ansosnten halt ein Temp Register + ein Mov befehl.
Mal ein Beispiel:
ldi ist 16 bit breit. 8 Bit davon werden schon mal für den zu ladenden
Wert benötigt. Bei 32 Registern würde man für die Registernummer
nochmals 5 Bit brauchen. Dann wären für den eigentlichen Befehl selbst
nur noch 3 Bit übrig. Damit würde ldi aus dem gesamten "Befehlsraum"
(16 bit = 65536 verschiedene mögliche Werte) alleine ein Achtel
belegen. Und es gibt ja noch einige weitere Befehle mit Immediate (adi,
subi, sbci, cpi, ori, andi). Da sieht man schon, daß das ziemlich eng
würde. Deshalb hat man hier bei der Registernummer ein Bit gespart, was
aber eben dazu führt, daß nur die Hälfte der Register mit diesen
Befehlen angesprochen werden kann.
es gab ganz am Anfang der AVRs (da gabs nur 1200, 2313 und 8515) die
Idee , eine Art Bankselect-bit einzuführen, da sollte R0 mit R16 usw.
getauscht werden, ein ldi r16, xx würde dann ein ldi r0,xx bedeuten.
Meiner Meinung nach zum Glück nie wirklich realisiert. Ich kann mit der
kleinen Einschränkung gut leben. Und wenn man in einer Hochsprache
programmiert, merkt man davon sowieso nichts.
Ich habe damit auch keine Probleme (meht). Wenn man erstmal verstanden
hat, dass der Adressbereich
- 16 "dumme" Register (kein immidiate)
- 16 "bessere" Register (incl. Doppelregister/Pointer)
- 32 "hochwertige" (und "schnelle") I/Os (Bit-Zugriff möglich)
- 32 "schnelle" I/Os (Byte-Zugriff mit IN/OUT)
- bis zu 160 "blöde" I/Os (Extendet-I/O im SRAM-Bereich)
- internes SRAM
- externes SRAM via Speicherinterface (noch nie benutzt)
hat, dann sollte man damit auch klarkommen.
Man muss sich eben mal mit der Architektur des AVRs vertraut machen,
die aber doch recht überschaubar ist.
...
um jetzt noch mal auf das eigentliche problem zurück zu kommen:
setze den zähler-wert auf den wert vor dem überlauf wert und dann lasse
den zähler überlaufen.
(Je nach dem welchen Modus du verwendest geht das oder auch nicht)
oder, wenn es nur auf die auslösung des interrupts auskommt, dann rufe
ihn einfach auf.