Forum: Mikrocontroller und Digitale Elektronik Timer1-Interrupt


von Hans-Georg Gamm (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

ich möchte gerne eine LED zum Blinken bringen. Die Zeit ist egal,
jedoch soll die Ein- und Ausschaltdauer gleich sein.
Irgendwas mache ich falsch. Kann mir jemand helfen. Die meisten werden
über dieses Problem wohl eher lachen :-)
Vielen Dank
Gruß
Hans-Georg

von Michael (Gast)


Lesenswert?

Schreibe doch einfach Kommentare in Deinen Code; es reicht schon,
main_anfang und main_ende. Dann sieht man doch gleich, was los ist.

von Hans-Georg Gamm (Gast)


Lesenswert?

Hallo Michael,

vielen Dank. Da hätte ich auch wirklich selber drauf kommen können.
Tage lang hing ich an diesem Problem. Vielleicht sollte ich mir
wirklich angewöhnen Kommentare zu schreiben.

von Michael (Gast)


Lesenswert?

Ich hoffe, daß Du nun auch den Stackpointer gesetzt hast ! (?)

von Achim Walther (Gast)


Lesenswert?

Ich nehme an, dass Du es jetzt korrigiert hast. Möchte trotzdem noch
meinen Senf dazugeben ;-)

    ldi R17, 0x01
    out DDRC, R17

musst Du nicht jedes Mal ausführen. Es reicht, wenn es einmal (z.B. in
Main) gesetzt wird.

    ldi R19, 0x00
    cp R19, R18
ist gleich
    cpi R18, 0

Den aktuellen Schaltzustand über PINC zu lesen ist m.E. unüblich. Du
könnest eines der vielen Register verwenden und das Togglen
vereinfachen. Für den konkreten Fall würde folgendes ausreichen:

TIMER:
        eor temp, temp
        out PORTC, R17
        reti

Gruß, Achim.

von Achim Walther (Gast)


Lesenswert?

Sorry, richtig wäre

TIMER:
        eor temp, temp
        out PORTC, temp
        reti

von Hans-Georg Gamm (Gast)


Lesenswert?

Hallo,

danke für die Tipps. Werde das gleich mal ausprobieren. Aber mit PINx
kann man doch eigentlich nichts weiter anfangen als den Zustand
abzufragen, oder?!
Das mit dem "eor" habe ich nicht ganz verstanden. Die Wertetabelle
sieht doch folgendermaßen aus:  0  0 -->  0
                                0  1 -->  1
                                1  0 -->  1
                                1  1 -->  0
Wenn ich jetzt ein Register mit sich selber durch ein XOR-Glied
schicke, dann ist es doch leer. Liege ich da richtig?? Wenn das so ist,
warum schreibe ich dann nicht einfach "clr temp"??

Nein, den Stackpointer habe ich nicht gesetzt. Ist das wichtig in
diesem Fall? Es geht doch auch so!! Oder sollte man sich das einfach
angewöhnen?
Gruß
Hans-Georg

von Peter D. (peda)


Lesenswert?

"Nein, den Stackpointer habe ich nicht gesetzt. Ist das wichtig in
diesem Fall? Es geht doch auch so!!"


Wenn es gegangen wäre, hättest Du doch nicht gefragt.

Gehen heißt doch nicht, daß es irgendwas macht, sondern daß es ganz
genau das macht, was man sich beim Programm schreiben gedacht hat.


Und damit man später noch weiß, was man sich dabei gedacht hat, sollte
man das Programm kommentieren. Z.B. was Du Dir gedacht hast, was nach
dem "sei" als nächstes ausgeführt wird.


Es ist ein großer Irrtum zu glauben, Kommentare sind nur, damits
schöner aussieht oder damit andere den Code abkupfern können.

Kommentare sind hauptsächlich für einen selbst da !!!


Peter

von Thomas Burkhardt (Gast)


Lesenswert?

Hi h-g-h

das mit dem EOR kommt tatsächlich auf's selbe raus, wie ein CLR. Ist
wahrscheinlich eine Angewohnheit aus Urzeiten, in denen das XOR
schneller war als ein MOV...

Zum Stackpointer: Setze ihn immer, das ist einfach eine sinnvolle
Angewohnheit. Die paar Zeilen fressen kein Brot und wenn doch benötigt,
werden sie wenigstens nicht vergessen.

von Peter D. (peda)


Lesenswert?

"Zum Stackpointer: Setze ihn immer, das ist einfach eine sinnvolle
Angewohnheit."


"Sinnvoll" ist aber stark untertrieben.

Es ist schlichtweg notwendig, sobald ein Call (Interrupts sind Calls)
verwendet wird.


Peter

von Philipp Sªsse (Gast)


Lesenswert?

Hallo Hans-Georg,

bevor ich zu dem eigentlich wichtigen Thema komme:

Du hast völlig richtig erkannt, der Vorschlag mit dem EOR tut es nicht!
Wenn es ein EORI gäbe (wie bei den meisten anderen Controllern), wäre es
sinnvoll: mit einem

EORI r18, 0b00000001

könntest Du einfach das letzte Bit toggeln.
Beim AVR muß man es eine Nummer komplizierter machen, z.B.

INC r18
ANDI r18, 0b00000001

oder ebenso gut

COM r18
ANDI r18, 0b00000001

Ist dann einen Hauch kompakter als mit Abfrage und Verzweigung, dafür
sollte man es aber wirklich kommentieren, damit man sich später
erinnert, was man da tut.


Im übrigen finde ich es durchaus okay, den aktuellen Zustand eines
Ausgangs aus dem PINC abzufragen -- warum nicht? Bei großen Programmen
ist man nachher froh, wenn man kein Register mit sowas blockiert. Man
kann sogar darauf verzichten, überhaupt ein Register zu benutzen, was
in einer Interrupt-Routine ja hilfreich ist, weil man das Register
sonst nicht im main benutzen dürfte:

TIMER:
  sbis PINC, 0     ;nicht zum Bitsetzen springen,
                         ;wenn schon gesetzt
        rjmp BIT_SETZEN
        cbi PORTC, 0     ;Bit 0 löschen
        reti
BIT_SETZEN:
        sbi PORTC, 0     ;Bit 0 setzen
        reti

Das ist kompakt, ohne Tricks und verändert weder ein Register noch ein
Statusbit, ist also eine enorm pflegeleichte Interruptroutine.

Und jetzt wird es wichtig:

Sobald Du mit TST oder EOR oder COM oder wasauchimmer operierst
veränderst Du Statusregister, mußt also entweder am Anfang der
Interruptroutine das Statusregister retten und am Ende wieder
herstellen oder Du wirst Dich im main nicht mehr auf irgendein
Statusbit verlassen können!

Enorm wichtiger Punkt für Leute, die vorher nur Hochsprachen genutzt
haben, die einem diese Arbeit abnehmen, auf so etwas zu achten. Die
eleganteste Möglichkeit sind Interruptroutinen, die alles in Ruhe
lassen (auch wenn Achim das unüblich findet).

Das geht natürlich nicht immer und in diesen Fällen: immer ans
Statusregister denken, sonst hat man nachher Fehler, die man ewig sucht
(weil man an der falschen Stelle sucht): im Debugger funktioniert der
Algorithmus ja, warum nicht in der Praxis? usw.

von Achim Walther (Gast)


Lesenswert?

Jetzt, wo Du nochmal die XOR-Tabelle aufgeschrieben hast, fällt mir auf,
dass der Befehl für das Togglen eines Bits wohl doch nicht geeignet ist.
Gesucht wäre ein Kommando, was das Bit / die Bits abwechselnd auf 0 und
1 setzt, ohne eine Verzweigung zu verwenden. Ohne es getestet zu haben,
tippe ich auf "COM temp" (Einer-Komplement)
Ich sollte öfter mal das Schild lesen: "Vor Öffnen des Mundwerks
Gehirn einschalten" ;-)

von Dirk (Gast)


Lesenswert?

Hi,

wenn es schon ein Mega44/8, Tiny13 o. Tiny2313 ist geht es sehr einfach
durch setzen des PIN's.

Beispiel LED toggeln an PINC.0:

sbi PINC.0

Ich finde es so sehr komfortabel und man hat keine Verzweigungen usw.

Mfg
Dirk

von Philipp Sªsse (Gast)


Lesenswert?

Hm? sbi toggelt doch nicht, sondern setzt. Ein "tbi" wäre eine feine
Sache, ist mir aber nicht bekannt. Wer von uns steht auf dem Schlauch?

von ...HanneS... (Gast)


Lesenswert?

cbi PORTx,y löscht das Bit,
sbi PORTx,y setzt das Bit,
sbi PINx,y toggelt das Bit, aber nur bei einigen modernen AVRs (siehe
Datenblatt)

von Hans-Georg Gamm (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

das mit dem COM-Befehl funktioniert. Sehr praktisch. Das Programm
verküzt sich merklich.
Wieso kann Register, die in der Interruptroutine benutzt werden, nicht
auch im main verwenden? Müsste doch trotzdem gehen. Dann kriegen sie
halt ständig einen neuen Wert rein geschrieben.
Das mit dem Statusregister retten klingt schon logisch. Daran muss ich
erst mal denken. Bei Hochsprachen ist das schon angenehmer :-)

Grüßli
Hans-Georg

von Peter D. (peda)


Lesenswert?

@Hans,

Du hast das falsche File angehängt. Wenn Du willst, daß es jemand
überprüft, dann muß es schon der Quelltext (*.asm) sein.


"Dann kriegen sie halt ständig einen neuen Wert rein geschrieben."

Witz du bist umzingelt.
Was nützt Dir ein Register, welches nur Zufallszahlen enthält ?
Z.B. Kontoauszüge einer anderen Person würden Dir ja auch herzlich
wenig nützen.

Man kann jedoch Register im Interrupt PUSHen und dann verwenden.
Aber wesentlich effektiver ist es eben, einige Register im Interrupt
und andere im Main zu verwenden.


Peter

von Hans-Georg Gamm (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

sorry, habe die falsche File angehängt. Jetzt noch mal die richtige.

OK, ja, habs gerafft wie das mit den Registern in der Interruptroutine
ist. Schon klar!!

von Philipp Sªsse (Gast)


Lesenswert?

sbi PINx? Tatsächlich! Wer (genau!) lesen kann, ist wohl doch im
Vorteil! (-; Allerdings ist es auch eine etwas krumme Tour, einen
Befehl schreibend auf ein Nur-lese-Register sachfremd zu mißbrauchen
... Trotzdem danke für die Aufklärung!

Hans-Georg, oben habe ich geschrieben, wie Du ganz ohne
Registerbenutzung auskommst; falls Dein AVR sbi PINx unterstützt, geht
es sogar nur mit diesem einen Befehl und RETI. Wenn Du bei der
COM-Lösung auch das Retten des Statusregisters mitzählst, ist sie
deutlich umständlicher!

Natürlich ist die Versuchung groß zu sagen, ich brache das Register ja
nur ganz kurz für eine Operation. Aber irgendwann wird der Interrupt
halt genau zwischen Reinschreiben und Rauslesen zuschlagen. Also fang
mit sowas gar nicht erst an -- zumal, wenn es sich so leicht vermeiden
läßt wie hier!

von Peter D. (peda)


Lesenswert?

Deine Programme werden solange nicht laufen, solange Du die Postings
anderer, den Stack betreffend, ignorierst.


Peter

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.