Hallo,
Bekomme keinen Timer0interrupt, jedoch einen TImer1interrupt schon.
Hab ein kleines Testprogramm geschrieben siehe unten.
Jedoch kommt auch da der Timer0 interrupt nicht.
Warum nicht? Übersehe ich einen kleine Fehler bei der Initialisierung?
Bitte um Hilfe
PS: Programm ist geschrieben für einen ATMEGA168
LG
cseg
;Beginn eines Code-Segmentes
.org 0x0000
rjmp init
;.org 0x001A
; jmp timer1_overflow ;INTERRUPT
.org 0x0020
jmp timer0_overflow
init:
ldi temp, HIGH(RAMEND)
out SPH, temp
ldi temp, LOW(RAMEND)
out SPL, temp
ldi r16, 0b11111110
out DDRD, r16
ldi r16, 0b00101111
out DDRB, r16
ldi r16, 0b11110101
out DDRC, r16
call Timer0_init
;call Timer1_init
sei
main:
jmp main
Timer1_init:
ldi temp,0b00000000
sts TCCR1A,temp
ldi temp,0b00000010
sts TCCR1B,temp
ldi temp,0b00000001
sts TIMSK1,temp
ret
Timer0_init:
ldi temp,0b00000000
sts TCCR0A,temp
ldi temp1,0b00000010
sts TCCR0B,temp1
ldi temp,0b00000001
sts TIMSK0,temp
ret
timer1_overflow:
push twitemp
push temp
push temp3
push temp2
push temp1 ; temp 1 sichern
in twitemp,sreg ; SREG sichern
out sreg,twitemp ; sreg wieder herstellen
pop temp1
pop temp2
pop temp3
pop temp
pop twitemp
reti ; das wars. Interrupt ist fertig
timer0_overflow:
in temp1,sreg
push temp1 ; temp 1 sichern
pop temp1
out sreg,temp1 ; sreg wieder herstellen
reti ; das wars. Interrupt ist fertig
> ldi temp1,0b00000010> sts TCCR0B,temp1
Das versteht keiner. Bzw. keiner hat die Bitbedeutungen im Kopf. Sieh
dir mal an, wie das mit den Bitnamen gemacht wird.
> .org 0x0020> jmp timer0_overflow> ldi temp,0b00000000> sts TCCR0A,temp> ldi temp1,0b00000010> sts TCCR0B,temp1> ldi temp,0b00000001> sts TIMSK0,temp
Tu dir selbst einen Gefallen und verwende die Definitionen und Namen,
die dir Atmel mitgibt. Dann braucht man nicht jeden Pfurz mit dem
Datenblatt auf Bitebene vergleichen, ob du irgendwo ein falsches Bit
gesetzt bzw. die falsche Adresse benutzt hast.
So wie das für mich aussieht, stimmt die ISR Adresse nicht.
TCCR0A und TCCR0B liegen im Adressraum so, dass sie mit einem OUT
erreicht werdenb können. Daher ist die Angabe der I/O Adresse bei einem
STS die falsche Adresse.
Schau ins m168def.inc rein und such dir TCCR0A.
Scroll ein bischen hoch. Bei den Registerm, bei denen "MEMORY Mapped" im
Kommentar dabei steht, musst du STS nehmen und die Defintion ist so,
dass du das auch mit der jeweiligen Register Adressdefinition auch tun
kannst. Steht nichts dabei, dann ist die Adresse so definiert worden,
dass sie für einen IN/OUT (oder auch CBI, SBI, etc. ) passt. Benutzt du
die für STS dann greifst du aufs falsche zu.
Ist dir denn im Simulator nicht aufgefallen, dass du keinen Vorteiler am
Timer gesetzt hast?
Franz schrieb:> .org 0x0020>> jmp timer0_overflow>>>> ldi temp,0b00000000 ;PWM Mode aus, Normal operation>> sts TCCR0A,temp>>> ldi temp1,0b00000010 ;Prescaler gesetzt auf 8>> sts TCCR0B,temp1>>> ldi temp,0b00000001 ;TOIE0: Timer/Counter0 overflow interrupt enable>> jmp timer0_overflow>>> 0x0020 TIMER0 OVF Timer/Counter0 overflow beim ATMEGA 168
Du hast es nicht verstanden, oder?
schreibst du
.org 0x0020
dann muss ich zur Kontrolle ins Datenblatt und mir raussuchen, ob die
0x20 auch bei diesem Prozessor tatsächlich stimmen. -> Aufwand.
bei
.org OVF0addr
brauch ich ÜBERHAUPT NICHTS tun! Atmel hat bereits dafür gesorgt, dass
für diesen speziell eingestellten Prozessor durch Angabe von OVF0addr
die korrekte Adresse des INterrupt-Handlers eingestellt wird. Und zwar
bei ALLEN Prozessoren, die einen Overflow Interrupt am Timer 0 auslösen
können.
Nein habs schon verstanden. War mein Fehler sorry.
Funktioniert jetzt nachdem ich sts auf out geändert habe bei dem Befehl:
>> ldi temp1,0b00000010 ;Prescaler gesetzt auf 8>> out TCCR0B,temp1
Ist mir nicht aufgefallen. Da hätt ich dann lange suchen können auf eine
Befehlsänderung wäre ich nicht gekommen.
Danke!
wo ist der Unterschied?
ob ich nun eine 2= b10 um null(CS00=0) Stellen schiebe
oder
ob ich nun eine 1= b01 um eine(CS10=1) Stelle schiebe
..
Das Ergebnis ist in beiden Fällen dasselbe.
Immerhin wollte er den Teiler aus der zweiten Zeile haben:
CSx2 CSx1 CSx0
(0) 0 0 0 Timer stopp
(1) 0 0 1 Clk/1
(2) 0 1 0 Clk/8
(3) 0 1 1 ...
Also, warum nicht gleich die zwei da eintragen?
Noch besser Erkennbar ist bei den Modes of Operations der Timer. Dort
steht die Zahl direkt vor der Tabellenzeile. Leider geht es dort nicht
so, weil die Bits verstreut liegen.
Matthias Lipinsky schrieb:> Also, warum nicht gleich die zwei da eintragen?
Weil sonst im Schiebe-Ausdruck nicht das "richtige" Bit angegeben wird.
Es wird impliziert, dass CS00 gesetzt wird, in Wirklichkeit ist es aber
CS01.
Klar, es resultiert in beiden Fällen ein Vorteiler von clk/8.
>Weil sonst im Schiebe-Ausdruck nicht das "richtige" Bit angegeben wird.
Doch. Wird es. in CS20:CS00 will ich eine ZWEI.
Es wird impliziert, dass CS00 gesetzt wird,
Das stimmt nicht. Es steht da, das die Zahl davor (hier zwei) ab dem Bit
CS00 eingetragen werden soll.
Bei Registern hat doch auch keiner Probleme: Z=R31:R30
ABer du kannst ja gern bei: