Forum: Mikrocontroller und Digitale Elektronik Timer 0 interrupt kommt nicht


von Franz (Gast)


Lesenswert?

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

von Matthias L. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> So wie das für mich aussieht, stimmt die ISR Adresse nicht.


Nö. Stimmt sogar.

Schreib trotzdem
1
.org  OVF0addr
2
    jmp timer0_overflow

dann braucht man sich um solche Sachen und auch nicht ob da jetzt eine 
Byteadresse oder doch eine Wordadresse hin muss, keine Gedanken machen.

von Franz (Gast)


Lesenswert?

.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

von Karl H. (kbuchegg)


Lesenswert?

Hier ist der Fehler
1
  ldi    temp,0b00000000
2
  sts    TCCR0A,temp
3
4
  ldi    temp1,0b00000010
5
  sts    TCCR0B,temp1

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?

von Franz (Gast)


Lesenswert?

Franz schrieb:
>>  ldi    temp,0b00000001   ;TOIE0: Timer/Counter0 overflow interrupt enable
>>  jmp timer0_overflow

hoppala
statt jmp timer0_overflow gehört natürlich: sts    TIMSK0,temp

von Karl H. (kbuchegg)


Lesenswert?

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.

von Franz (Gast)


Lesenswert?

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!

von Matthias L. (Gast)


Lesenswert?

Und mach das richtig:
>>>  ldi    temp1,0b00000010  ;Prescaler gesetzt auf 8

zu:
1
ldi    temp1, (2<<CS00)  ;Prescaler gesetzt auf 8

von Hawa M. (hawamand)


Lesenswert?

Matthias Lipinsky schrieb:
> Und mach das richtig:
>>>>  ldi    temp1,0b00000010  ;Prescaler gesetzt auf 8
>
> zu:
>
1
> ldi    temp1, (2<<CS00)  ;Prescaler gesetzt auf 8
2
>
wohl eher zu:
1
ldi    temp1, (1<<CS01)  ;Prescaler gesetzt auf 8

von Matthias L. (Gast)


Lesenswert?

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.

von Hawa M. (hawamand)


Lesenswert?

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.

von Matthias L. (Gast)


Lesenswert?

>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:
1
TCCR0A |= (1<<CS02) | (1<<CS01) | (1<<CS00);

bleiben. Ich bleibe bei
1
TCCR0A |= (7<<CS00);

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.