Forum: Mikrocontroller und Digitale Elektronik timer interrupt


von Markus M. (seeadler78)


Angehängte Dateien:

Lesenswert?

Hallo
Kann mir jemand helfen.Ich bekomme es nicht hin das der Timer bei einem
Interrupt in das Label Licht_80s springt.Weiss nicht wo der Fehler
liegen könnte.Bin für jede Hilfe dakbar

von Paul Baumann (Gast)


Lesenswert?

Unterscheidet Assembler in Groß/Kleinschreibung? Du hast Licht_80s
und licht-80s geschrieben. (Ich verstehe nicht viel von Assembler, nur
das ist mir aufgefallen)

MfG Paul

von Markus M. (seeadler78)


Lesenswert?

Hi
Nee interrissiert Assambler nicht.
aber danke
seeadler78

von Magnus Müller (Magnetus) (Gast)


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

von Markus M. (seeadler78)


Lesenswert?

Hi
Weil ich mir nicht sicher war ob sie freigegeben werden.und da dachte
ich mir doppelt hält besser.Aber Danke

von Magnus Müller (Magnetus) (Gast)


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?

von Paul Baumann (Gast)


Lesenswert?

Was freue ich mich, daß es BASCOM gibt!
:-)
Paul

von Markus M. (seeadler78)


Angehängte Dateien:

Lesenswert?

Hi
Habs geändert.Trotzdem ändert es ja nicht an dem Problem.
seeadler78

von Sebastian (Gast)


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

von Michael U. (Gast)


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

von johnny.m (Gast)


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.

von Markus M. (seeadler78)


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

von Karl H. (kbuchegg)


Lesenswert?

Mal ehrlich: Das steht alles in den Datenblättern
Ich versteh wirklich nicht, wie jemand (du bist ja
nicht alleine) einen µC programmieren kann ohne die
Datenblätter neben sich liegen zu haben.

Einfach den Vorteiler komplett wegnehmen und der
Timer bleibt stehen.

von Markus M. (seeadler78)


Lesenswert?

Hi
Hast ja recht,aber trotzdem danke

von Hannes L. (hannes)


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

...

von Markus M. (seeadler78)


Lesenswert?

Hi
Vielen Dank.werde mir das ganze zu Herzen nehmen.
bis dann Seeadler78

von Karl H. (kbuchegg)


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.

von Hannes L. (hannes)


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

...

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.