timer interrupt

Gast #346080
Lesenswert?
• ▲
▼
Ähm... es wird dir zwar nicht bei der Lösung deines Problems helfen,
aber:

bewirkt

--> ldi temp,128
--> out SREG,temp

und

-->sei

nicht ein und das selbe? Wenn ja, warum gibst du die INTs doppelt
frei?

Gruß,
Magnetus
Gast #346082
Lesenswert?
• ▲
▼
Oh... habs gerade selber gemerkt... ist nicht das selbe.

--> sei

...setzt das I-Bit im SREG

--> ldi temp,128
--> out SREG,temp

...setzt das I-Bit und löscht alle anderen! ...warum tust du das?
Gast #346085
Lesenswert?
• ▲
▼
Wer aufpasst bei der Simulation wird schlau:
Der Interrupt tritt sehr wohl auf, du hast aber dein "rjmp Licht_80s"
eine Zeile zu weit unten geschrieben bzw. ein "rjmp RESET" zu viel
drüber.
Ratsam ist immer die benuzten stellen nochmal explizit mit .org an die
entsprechende Speicherzelle zu rücken. Wenn dann ein "rjmp RESET" zu
viel drin is beschwert sich der Assambler.

Sebastian

PS: Lang bleibt das Licht ja nicht an...
Gast #346086
Lesenswert?
• ▲
▼
Hallo,

ich habe mal ein paar Stellen hier reinkopiert, die mich verwirren:

.include <tn2313def.inc>

ist also ein Tiny2313


      rjmp RESET
         rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp Licht_80s
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET
      rjmp RESET

Mehr als Anregung: wenn Du IRQs nicht benutzt, setze reti statt rjmp
RESET.
Hat den Vorteil, das ein versehentlich ausgelöster IRQ eben einfach als
bearbeitet verlassen wird.


reset:
    ldi temp,128      ;gibt die interrupts frei
    out SREG,temp
Daß das überflüssig ist, wurde ja oben schon diskutiert.

Ein Prozessor macht nicht unbedingt was er soll,
er macht aber IMMER, was man ihm gesagt hat. ;-)

    ldi temp,0b00000000
    out ddrd,temp      ;portd ist eingang

Ich weiß zwar nicht, was an PortD bei Dir dran ist, falls es offene
Pins gibt, unbedingt die internen PullUps einschalten. Ein offener
Eingang nimmt jeden Pegel an, die Nebenwirkungen sind genauso
unberechenbar.

    ldi Temp, 2        ;hier wird der timer interupt freigegeben
    out TIMSK, Temp

Du hast dem Timer immernoch gesagt, in welchem Mode mit welchen Werten
er eigentlich laufen soll, der kann nicht hellsehen...

    sei
Warum gibst Du hier die Interrupts frei, ohne überhaupt irgendwas
initialisiert zu haben? Das kann dazu führen, daß schon ein IRQ
ausgelöst wird, bevor Du die Zugehörigen Daten vorbereitet hast.


    ldi temp,5
    out TCCR0,temp      ; mit 1024 geteilte frequenz

Das Register TCCR0 ist nur aus Kompatibilitätsgründen zu Vorgängertüpen
auf das Register TCCR0A definiert,
der Tiny2323 hat TCCR0A und TCCR0B.
Man sollte auch immer mit den aktuellen Registernamen arbeiten...

timer:  ldi tmp , 255
     out TCNT0, tmp      ;timer zählt bis 255

Hier setzt Du nun endlich den Zählwert des Timers, daß muß vor SEI
passieren. Es ist immernoch unklar (wenigstens als Kommentar für uns
hier) in welchem Mode er läuft...).

Warum setzt Du das hier überhaupt???

    ldi temp,0
    cp zahl,temp
    breq licht_aus
    rjmp timer



licht_aus:
           ldi temp,0b11111111
       out portb,temp
       rjmp ende


Licht_80s:
In der IRQ-Routine wird nur dec Zahl gemacht.
Wenn der Timer im One-Shot-Mode läuft, zählt er genau bis 0 und bleibt
dann stehen, es wird also nie was weiteres passieren...
Dazu müsste hier TCNT0 wieder gesetzt und der Timer gestartet werden.

Habe gerade mal nachgesehen, er müsste im Normal-Mode sein, damit zählt
er aufwärts, also von Deinen 255 direkt auf 0, danach immer von 0...255
usw.
Damit müsste Dein Licht genau einen Taktzyklus lang leuchten, falls Du
es beim Reset einschaltest.
Etwas kurz?

      in sregsave ,SREG
      push sregsave
      dec zahl
      pop sregsave
      out SREG,sregsave
      reti


ende:

    rjmp ende

Gruß aus Berlin
Michael
Gast #346087
Lesenswert?
• ▲
▼
> timer: ldi tmp , 255
>     out TCNT0, tmp  ;timer zählt bis 255

Das halte ich für ein Gerücht. Wenn Du in TCNT0 255 reinschreibst, dann
läuft er genau beim nächsten Takt über, da es sich um einen 8-Bit-Timer
handelt.

Was ganz gefährlich ist, ist die Freigabe der Interrupts VOR der
Initialisierung des Stack Pointers. Weg damit!

Habe den Eindruck, Du solltest Dich vielleicht mal in Ruhe hinsetzen
und ein Ablaufdiagramm von Deinem Programm zeichnen und jeden Abschnitt
mal anhand des Datenblattes auf seinen Sinn überprüfen. Da es kein
sonderlich langes und kompliziertes Programm ist, sollte das in
endlicher Zeit machbar sein.
OP #346088
Lesenswert?
• ▲
▼
hallo
Danke für die Tipps.habe irgendwo im Internet gelesen das wenn die 255
in das TCNT0,der Zähler bis 255 zählt.Das war dann die ganze Zeit in
meinem Kopf.Habe es jetzt geändert.Aber noch ne Frage.Lässt sich der
Timer wieder abstellen oder kann ich nur den Interrupt verbieten.
Danke seeadler78
#346091
Lesenswert?
• ▲
▼
Schau dir doch einfach mal im Datenblatt die Register des Timers an.
Dann wirst du sehen, dass du jederzeit die Einstellungen des Timers
verändern kannst, also kannst du ihn auch abstellen, auf anderen
Vorteiler umstellen, Betriebsart umschalten usw...

Man gut, dass es Datenblätter gibt... ;-)

Übrigens läuft bei mir so ziemlich jedes Programm mit einem Timer im
Hintergrund, der in regelmäßigen Zeitabständen diverse Aufgaben
erledigt (Tasten entprellen, Software-Timer behandeln, manchmal auch
PWM erzeugen, usw.). Meist schubst der Timer-Int auch die nächste Runde
der Mainloop an, in der die hauptsächliche Arbeit gemacht wird, und wo
der AVR nach getaner Arbeit in den Sleep geschickt wird, aus dem er vom
nächsten Interrupt geweckt wird.

Dein Programm erscheint mir recht konfus, die meisten Mängel wurden
aber bereits genannt. Du solltest dir angewöhnen, zu jeder
Programmzeile Überlegungen anzustellen, warum du das so und nicht
anders machen willst. Dann gehört zu (fast) jeder Programmzeile ein
Kommentar, der aber nicht unbedingt den benutzten Befehl erklären soll,
sondern was dieser Befehl in diesem konkreten Fall an der Gesamtaufgabe
bewirken soll. Du solltest dir auch mal die Register r0..r15 ansehen.
Die Tatsache, dass die nicht mit Konstanten operieren können, macht sie
nicht unbenutzbar. Für SREG-Sicherung sollte man daher ein unteres
Register verwenden, die oberen sind dazu zu wertvoll. Ähnlich gilt das
für andere Aufgaben, in denen nicht mit Konstanten operiert werden
muss.

Ich weiß, aller Anfang ist schwer. Vielleicht solltest du dir mal die
Programme anderer Leute etwas genauer ansehen und versuchen zu
verstehen. Wenn du etwas im Forum herumblätterst, dann wirst du eine
Menge Beispielcode finden. Mit der Suchfunktion wirst du allerdings
nicht allzuviel finden, da der Betreff eines Threads in den seltensten
Fällen dem tatsächlichen Thema entspricht...

Beste Grüße, auch an alle Nicht-ASM-Programmierer... ;-)

...
#346093
Lesenswert?
• ▲
▼
> Ich weiß, aller Anfang ist schwer. Vielleicht solltest du dir
> mal die Programme anderer Leute etwas genauer ansehen

Den Vorschlag unterstütze ich zu 100%.
Da lernt man eine Menge.

Wenn du einen (meiner Meinung nach) erstklassigen
Assmebler-Code sehen und studieren willst, dann geh
mal auf die Website vom Hannes.

http://hanneslux.de/avr/index.html

So guten Code sieht man selten.
#346094
Lesenswert?
• ▲
▼
> Wenn du einen (meiner Meinung nach) erstklassigen
> Assmebler-Code sehen und studieren willst,

Sorry... - Das kann ich so nicht stehen lassen. Erstklassigen ASM-Code
gibt es vielleicht bei PeDa oder anderen wirklichen Könnern.

Bei mir gibt es allerhöchstens gut lesbaren bzw. gut verständlichen
Anfängercode, der allerdings meist üppig und verständlich kommentiert
ist. Viele der auf meiner Webseite vorhandenen Programme sind (aus
heutiger Sicht) alles andere als optimal programmiert. Ich werde aber
nicht alle alten Programme (die ja ihre Aufgabe erfüllen) neu
schreiben, nur weil ich inzwischen bessere Möglichkeiten kenne.

Dem Anfänger konnen diese Programme aber schon den richtigen Weg
zeigen.

Man gut, dass es AVRs gibt... ;-)

...

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