Atmega32 Timer0 und Timer1

Gast #2949705
Lesenswert?

Hallo,
ich programmiere normalerweise in Bascom muss aber diesmal etwas in 
Assembler machen was komplettes Neuland für mich ist.

Im Anhang ist eine Datei in der ich mich versucht habe die beiden Timer 
des Atmega32 (Timer0 und Timer1 zu aktivieren), Timer0 soll 10000mal pro 
sek einen Interrupt auslösen und Timer1 2mal pro sek. Kann da vielleicht 
mal einer drüberschauen und mir sagen was ich da falsch mache, hab mich 
auch schon über Timer in Assembler eingelesen aber so wirklich hab ich 
das nicht verstanden. Timer0 macht so halbwegs was er soll aber Timer1 
noch nicht so richtig und beide zusammen tuns auch noch nicht so 
richtig.

Wäre dankbar über eure Hilfe!

Vielleicht kann mir ja jemand bei dem Code helfen.

Danke

schöne Grüße.
Angehängte Dateien:
Gast #2950777
Lesenswert?

danny_v1 schrieb:
> OK,
>
> ich würde mal schätzen das die ans Ende des Interrupt gehören, bin mir
> aber nicht sicher.

Richtig.

> Aber das kann ja eigentlich noch nicht der ganze Fehler sein.

Warum nicht? Wenn nicht zu jedem push exakt ein pop gemacht wird, kommt 
alles komplett durcheinander. Ich bin erstaunt, daß überhaupt irgendwas 
so ähnlich funktioniert wie gedacht.

danny_v1 schrieb:
> Soweit ich das verstanden habe sichere ich mit dem push, mein Register
> (temp)

Genauer: Du kopierst den Wert auf den Stack, also in den Speicher. Der 
Stack ist dabei wie ein Stapel aufgebaut (daher der Name). Das nächste 
push legt dann quasi den nächsten Wert auf den Stapel drauf.

> und mit dem pop geb ich den wert wieder auf das Register temp
> zurück, oder?

Mit pop wird der zuletzt auf dem Stack gespeicherte Wert wieder 
zurückgelesen in das Register, das du angibst. reti benutzt übrigens 
auch den zuletzt auf dem Stack gespeicherten Wert als 
Rücksprung-Adresse. Und jetzt überleg mal, was passiert, wenn du ein 
push ohne dazugehöriges pop machst und danach ein reti.
Gast #2950817
Lesenswert?

dann spring ich zur falschen Adresse, da der falsche Wert im Stack noch 
oben drauf liegt, richtig? Also müsste das im Beispiel vom Timer0 dann 
so Aussehen???

timer0_overflow:
  push  TEMP
  in  TEMP,SREG
  push  TEMP
  ldi TSW,timerwert
  out tcnt0,TSW
;..........Programmcode Timer0
  pop temp
  out SREG, temp
  pop temp
reti
Gast #2950979
Lesenswert?

Gut, da bin ich ja schonmal ein Stück weiter. Mit dem Timer1 
funktioniert das dann ja sicher genauso.

Macht es einen Unterschied ob ich den Interrupt mit "rjmp" oder "call" 
aufrufe???

Und dann hab ich festgestellt das das Programm nur funktioniert wenn ich 
nach jeden Interrupt die Timer neu initialisiere, ist das normal???
#2951136
Lesenswert?

danny_v1 schrieb:
> und woran liegt das dann?
> wäre schön wenn mal jemand was konkretes schreiben würde wie ich den
> code abändern muss.

Es wäre schön, wenn du mal ein bischen mitdenken würdest.
Und es wäre schon, wenn du dir wenigstens die absoluten Grundlagen im 
AVR-Tutorial mal reinziehen würdest.

Wenn du Code mittels einem CALL aufrufst, wie kommt man denn dann wieder 
an die aufrufende Stelle zurück?
mit einem Return (ret oder reti)

Wenn du also hier
1
.ORG OVF0addr                ;Bei Overflow Timer0 Sprung zu
2
    call timer0_overflow        ;Timer0_overflow
3

4
.ORG OVF1addr                ;Bei Overflow Timer1 Sprung zu
5
    call timer1_overflow        ;Timer1_overflow

mit einem Call aus dem Interrupt Vektor in die eigentliche 
Funktionalität verzweigst, wo landest du dann nach dem reti? Zb in dem 
reti, der irgendwann in timer0_overflow passiert?


Und ist das das, was eigentlich passieren sollte?
Und wie passt das ins Bild, wenn du weißt, dass bei Auftreten und Beginn 
der Interrupt Abarbeitung der Prozessor die Verzweigung in den Interrupt 
Vektor selbst mit einem Call macht. Mit einem Call machen muss, weil die 
Programmausführung ja wieder an die Stelle zurückkehren muss, die 
eigentlich vom Interrupt unterbrochen wurde. Und genau das macht ja ein 
Call. Wenn da also an diesen impliziten Call dann selbst auch noch einen 
Call hinten nach ausführen lässt ....
Gast #2951268
Lesenswert?

Ok habs hinbekommen. Das Interrupt Tutorial war sehr hilfreich! Ja das 
mit dem call und rjmp leuchtet mir jetzt ein.
Der Hauptfehler war das ich das TIMSK Register doppelt beschrieben hab 
(dachte jeder Timer hat sein eigenes).

Danke für eure Hilfe.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren