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
Schreibe doch einfach Kommentare in Deinen Code; es reicht schon, main_anfang und main_ende. Dann sieht man doch gleich, was los ist.
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.
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.
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
"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
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.
"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
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.
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" ;-)
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
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?
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)
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
@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
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!!
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!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.