Hallo, ich habe folgendes Problem, ich würde gern 8 LEDS (die Kanäle eines Multiplexers darstellen) vorwärts, rückwärts und random laufen lassen. Beim Umschalten, was über einen Interrupt (int1) ausgelöst wird, lasse ich die Leds einmal in der jeweiligen Richtung durchlaufen und springe dann ins normale Programm zurück. Der Durchlauf dauert ein ganzes Stück, und sollte eigentlich noch zur Interrupt Routine gehören (also die Interrupts sollten eigentlich gesperrt sein), jedoch löst er wenn die LEDS zum Beispiel vorwärts durchlaufen und ich die Taste drücke den Interrupt trotzdem aus, und die Leds laufen rückwärts (ihc hoffe mal das war verständlich erklärt^^). Bekomm das leider nicht raus, kann mir irgendwer Helfen? Gibt es irgendeine Einstellung wo das verhalten während eines Interrupts gesteuert wird? (Hab in meinem Buch nichts weiter gefunden. Vielen Dank schon mal
Ich habs aufgegeben. 1000 x reti (Rücksprungpunkte) Das ist ein beschissener Prog.-stil! Eine ISR sollte einen Einsprungpunkt und EINEN Ausprungpunkt haben. Wenn man das nicht durchzieht, braucht man sich über so ein Programmverhalten nicht wundern. Ich vermute das Du ein reti erwischt, ohne es zuwollen. (evtl. in einer als vermeindliche Sub aufgerufenen Routine) Dadurch wird der Int. enabled ohne mit der ISR fertig zu sein. Korrigiere das bitte! Gruß Z8
habs gefunden! ... genau so ist es!!!! Zuerst wird genTast angesprungen, danach breq auf modech. In modech ein reti (was mit Sicherheit nicht gewollt ist!)
Schau Dir bitte mal den Unterschied zwischen ret und reti an! Ich denke es kankt daran. Gruß Z8
Hmm, doch das reti in modech ist so gedacht. Wenn er modech ausgeführt hat, dann hat er das Register wo die Richtung drin steht geändert, und könnte eigentlich zurückspringen. Hab jetzt die Interrupts noch mal per Hand gesperrt und wieder aktiviert (was ja eigentlich quatsch ist) und mir ist aufgefallen, dass wenn ich während der Interruptroutine ein zweites mal die Taste drücke, er die Routine zuende ausführt, aber danach, den nächsten Interrupt bearbeitet, anstatt ihn zu ignorieren, da er ja während eines anderen Interrupts ausgelöst wurde. Selbst wenn ich die Interruptroutine ca 8 sek. lang mach, und nach einer Sekunde den int0 auslöse, dann arbeitet er den 8sekündigen gar ab, um danach den nächsten zu bearbeiten. Kann man das verhalten irgendwo sperren?
>Selbst wenn ich die Interruptroutine ca 8 sek. lang mach
Du solltest dein Softwarekonzept mal überdenken!
eine typische ISR sieht so aus: isr: push push push rcall sub1 rcall sub2 rcall sub3 pop pop pop reti sub1: . . ret sub2: . . ret sub3: . . ret Wenn Du soweit bist, kannst Du auch vorher zurückspringen. Aber unter Beachtung des Stack! Z8 :)
eine typische ISR sieht so aus: isr: push push push rcall sub1 rcall sub2 rcall sub3 pop pop pop reti sub1: . . ret ; *wenn hier jetzt ein reti steht funktioniert das Prog.* ; *aber für den Rest der ISR ist der Int. frei gegeben* sub2: . . ret sub3: . . ret Wenn Du soweit bist, kannst Du auch vorher zurückspringen. Aber unter Beachtung des Stack!
Es tut mir wirklich leid, aber ich bin noch ein wenig Anfänger, deshalb weiß ich nicht wirklich was man bei einer isr tun oder lassen sollte. Hab ein Buch "Mikrocomputertechnik mit Controlern der Atmel..." hier, aber da stand nichts weiter die Interrupts betreffend. Wenn ich dass da richtig verstanden hab, ist der Unterschied zwischen ret, und reti, dass reti neben der Funktion von ret (an die Ursprüngliche Adresse+2 zurückspringen) noch die Interrupts wieder freischaltet. Das mit den 8 sek war eigentlich nur als Test gedacht um das zu verstehen. Mich hat es gewundert, dass er einen Interrupt während der Routine speichert und ihn danach ausführt (wenn die Interrupts wieder freigeschalten sind). Ich hab das jetzt auch so umgeschrieben, dass ich nur 1x reti habe, in den Routinen "ruckdurch" "zufalldurch" "vordurch" und "wartex10ms" gibt es keine keine reti, nur ret. Hab mir jezt echt Mühe gegeben^^, aber während der isr ausgelöste Interrupts (die er eigntlich ignorieren sollte), speichert er sich irgendwie ab, und nach Abarbeitung der Isr, arbeitet er den zweiten, nicht mehr ausgelösten Interrupt ab.
Christian Deeg wrote: > Hab mir jezt echt Mühe gegeben^^, aber während der isr ausgelöste > Interrupts (die er eigntlich ignorieren sollte), speichert er sich > irgendwie ab, und nach Abarbeitung der Isr, arbeitet er den zweiten, > nicht mehr ausgelösten Interrupt ab. Die speichert der nicht "irgendwie" ab. Wenn ein Hardware-Ereignis auftritt, zu dem ein Interrupt gehört, wird das dazugehörige Flag gesetzt. Und zwar immer (sofern es nicht schon gesetzt ist), völlig egal, ob die Interrupt-Bearbeitung freigegeben ist oder nicht. Wenn der dazugehörige Interrupt freigegeben wird und das Flag bereits gesetzt ist, dann wird der entsprechende Interrupt Handler ausgeführt. Abgesehen davon: Die Dateierweiterung für Assembler-Quelldateien ist nicht .txt, sondern .asm! Wenn Du Deinen Code als *.asm schickst, wird der auch vernünftig formatiert angezeigt. Darüberhinaus solltest Du auch mal einen Blick ins AVR-Tutorial werfen. Da wird vieles leicht verständlich erklärt...
Wenn Interrupts gesperrt sind, dürfte er aber doch die Flag für das Hardwareereignis nicht setzen, oder? Das mit dem .asm tut mir Leid, hab nur fix aus dem Programm rauskopiert. Also er setzt während einer Isr den Flag, was er ja eigentlich nicht machen sollte, weil das ja gesperrt ist oder? (Der Interrupt reagiert auf ansteigende Flanke, die Taste ist am Ende der 1. Isr aber schon wieder losgelassen).
Hi Christian,
>speichert er sich irgendwie ab
das ist normal! Du machst "eigendlich" nichts falsch!
Wenn Du soooolange ISRs hast, (macht man eigendlich nicht!)
must Du "anhängige Ints" kurz vor Ende in Deiner ISR löschen.
siehe:
General Interrupt Flag Register – GIFR
ldi r16 , 0
out GIFR, r16 ;löschen von anhängingen ext. Ints
reti
hab jetzt nicht mehr in Erinnerung, ob Du das level-gesteuert machst,
dann trift das nicht zu.
Gruß Z8
Christian Deeg wrote: > Wenn Interrupts gesperrt sind, dürfte er aber doch die Flag für das > Hardwareereignis nicht setzen, oder? Nochmal: Das Flag wird immer gesetzt, wenn das entsprechende Hardware-Ereignis auftritt! Ansonsten könnte man keine Hardware-Ereignisse durch Polling abfragen. Die "Interrupt-Freigabe" steuert nur die Bearbeitung des Hardware-Ereignisses als Interrupt Request. > Also er setzt während einer Isr den Flag, was er ja eigentlich nicht > machen sollte, weil das ja gesperrt ist oder? (Der Interrupt reagiert > auf ansteigende Flanke, die Taste ist am Ende der 1. Isr aber schon > wieder losgelassen). Siehe oben. Und Du solltest Dich mit Entprellung befassen. Das Prellen ist nämlich schätzungsweise der Grund dafür, dass das Flag erneut gesetzt wird. Die Auswertung mechanischer Kontakte über Interrupts ist sowieso nicht ratsam.
>Wenn Interrupts gesperrt sind, dürfte er aber doch die Flag für das >Hardwareereignis nicht setzen, oder? Doch. Tritt das Ereignis auf, wird das Flag gesetzt. Ist die zugehörige ISR nicht freigegeben, bleibt es beim gesetzten Flag. Sonst wird die ISR aufgerufen und das Flag gelöscht. >Also er setzt während einer Isr den Flag,.. Falls das Ereignis während der Abarbeitung der ISR nochmal auftritt, ja. > die Taste ist am Ende Tasten prellen und gehören grundsätzlich nicht per Interrupt abgefragt.
Doch. Das Flag wird immer gesetzt, wenn ein Ereignis auftritt. Aber wenn der Interrupt gerade gesperrt ist, springt er halt nicht in die Routine. Aber merken dass da was war tut er sich schon. Ist ja auch richtig so. Er soll ja jeden Interrupt mitbekommen. Du hast als Programmierer dafür zu sorgen, dass jedes Ereignis auch bearbeitet wird und genau desshalb macht man die ISR so kurz wie möglich und nicht mehrere Sekunden lang. Sven PS: Bin wohl zu langsam auf der Tastatur....
Ahh, ich hab das Sekundenlang gemacht, um mir eben dieses Verhalten zu erklären, jetzt erscheint mir das auch logisch. Ich wollte extra den Interrupt nehmen weil ich dacht dass ich dadurch die Taste entprellen kann (was ja auch funktionieren würde, wenn er denn die Flag nicht trotzdem speichern würde). Aber jetzt werde ich wohl doch den steinigen Weg nehmen^^. Oder kann man vllt die Flag irgendwie vor Ende des Interrupts löschen?
>Oder kann man vllt die Flag irgendwie vor Ende des >Interrupts löschen? Sicher. Indem du eine EINS auf dieses Bit schreibst. Das löst aber dein Entprellproblem nicht!
Hey Matthias, eine NULL! schreibst. Reden wir vom gleichen Bit im GIFR-Register ?
>eine NULL! schreibst. eine EINS: >>When an event on the INT1 pin triggers an interrupt request, INTF1 >>becomes set (one). >>If the I-bit in SREG and the INT1 bit in GICR are set (one), the MCU >>will jump to the corresponding >>Interrupt Vector. The flag is cleared when the interrupt routine is >>executed. >>Alternatively, the flag can be cleared by writing a logical one >>to it. This flag is always >>cleared when INT1 is configured as a level interrupt.
>>>When an event on the INT1 pin triggers an interrupt request, INTF1 >>>becomes set (one). -> also eine NULL! wenn ich nicht will, das ein "nachfolgendes Ereignis" einen Int. auslösen soll. Der Phasenschieber :)
Du solltest den von mir zitierten Abschnitt nochmal, und vollständig lesen!
was ? >the flag can be cleared by writing a logical one >to it was, was, was? nach einem Reset ist dieses Bit 0, also dürfte eine 1 einen änhängigen Int. signaliesieren. ?
>nach einem Reset ist dieses Bit 0, also dürfte eine 1 >einen änhängigen Int. signaliesieren. ? Beides korrekt. Aber es ging darum, ein gesetztes Bit zu löschen.
>>Alternatively, the flag can be cleared by writing a logical one >>to it ich halte das für eine Datenblattente!
Nein, dass ist keine Ente! Grund: diese Interruptflag befinden sich meist irgendwo in Konfigurationsregistern für die zugehörige Funktionseinheit. Beim ADC des Mega32 z.B. ist das Flag ADIF im Register ADCSRA enthalten. Wenn man nun in dieses Register schreiben will, kann man dabei dieses Bit einfach ignorieren und dort eine Null schreiben, das beeinflusst das Flag nicht. Man muss also nicht erst den aktuellen Wert des Flags auslesen, um es beim Schreibzugriff nicht ungewollt zu löschen.
>>>Alternatively, the flag can be cleared by writing a logical one >>>to it >ich halte das für eine Datenblattente! Mag sein, aber interessanterweise funktioniert es so. MfG Spess
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.