Befehle im Interrupt

OP Persönliche Seite #893669
Lesenswert?

Hallo zusammen!

Ich hab kürtzlich ein Assembler-Programm geschrieben für einen ATINY12.
Es geht hierbei um ein Zeitrelay, das ich mit einem BCD-Codierschalter 
in der Zeit variabel mache. Ich benötigte also, mit den 4 für den 
Schalter einen Eingang als Trigger (Int0) und ein Ausgang, alle Pins 
inclusive Reset-Pin.

Ich programmierte also ein Programm was aus einem Init, einer 
Endlosschleife und 2 Interruptroutinen (INT0 und Timer) bestand. (Im 
Anhang)

Ich wollte, dass ich nur Triggern kann, wenn der Ausgang nicht aktiv 
ist.
Also hab ich (mit % markiert) entsprechende Befehle innerhalb der 
Intteruptroutinen verwendet.

Resultat:
Die Zeit läuft "meistens" doppelt so lange. Wahrscheinlich, setzt er den 
Timmer nicht zurück.
und
Ich kann während des aktiven Ausgans triggern, was ich wiederum auf die 
Interruptsroutinen zurückschliese.

Nach langem probieren hab ich alles in ein Hauptprogramm geschrieben, 
welches auf die jeweiligen "kurzgeschriebenen" Interruptrourinen wartet. 
Jetzt gehts!!!

Meine Frage hier also: Warum kann ich in einer Interruptroutine nur 
beschrängt Befehle verwenden und welche funktionieren?
#893699
Lesenswert?

Daniel,

>>das problem ist, wenn in interrupt-routinen zu viele befehle stehen. da
>>die interrupts nicht unterbrechbar sind gehen welche verloren solange
>>eine isr läuft.

Stimmt, ist jetzt aber etwas missverständlich ausgedrückt....
Nur zur Sicherheit:
Es KÖNNEN interupts verloren gehen, Befehle nicht.
Jedenfalls solange keine verschachtelten Interupts programmiert werden, 
was übrigens sehr wohl geht, aber mit Tücken behaftet ist.

Jochen Müller
#893727
Lesenswert?

Steven W. wrote:

> Also ich gehe jetzt mal davon aus, dass das AVR-Studio nicht ganz so wie
> ein µC simuliert. Kurzum verwendet es keinen Stackpointer, sonst müsste
> ja auch hier Fehler geben.

Natürlich simuliert es auch den Stack-Pointer. Dass du keinen Fehler 
bekommst, obwohl du ihn nicht initialisierst, liegt daran, dass der 
ATtiny12 nur einen 3-Stufen Hardwarestack hat (weil er kein RAM hat). 
Und dieser Hardwarestack muss nicht initialisiert werden.
#893751
Lesenswert?

Steven W. wrote:
> @Stefan
>
> Warum muss ich ihn dann initialisieren, wenn ich ihn nicht
> initialisieren muss? :-)
>
> Paradoxisch!
>
> Gruß Ovular

Du musst ihn nicht initialisieren, da er (mangels SRAM) in Hardware 
werkelt. Du musst nicht immer alles glauben, was Taschenbuch schreibt, 
schau lieber ins Datenblatt. ;-)

...
Gast #893756
Lesenswert?

> Warum muss ich ihn dann initialisieren, wenn ich ihn nicht
> initialisieren muss? :-)

Jochen Müller ist in seinem ersten Beitrag einem Irrtum erlegen. Die
Initialisierung braucht man bei allen neueren AVRs, da diese
On-Chip-RAM haben und den Stack dort ablegen. Zu den alten RAM-losen
Typen mit Hardware-Stack gehören außer dem Tiny12 noch der Tiny11 und
der Tiny15. Alle anderen dürften mittlerweile vom Markt verschwunden
sein.
#893761
Lesenswert?

yalu wrote:
> Jochen Müller ist in seinem ersten Beitrag einem Irrtum erlegen. Die
> Initialisierung braucht man bei allen neueren AVRs, da diese
> On-Chip-RAM haben und den Stack dort ablegen. Zu den alten RAM-losen
> Typen mit Hardware-Stack gehören außer dem Tiny12 noch der Tiny11 und
> der Tiny15. Alle anderen dürften mittlerweile vom Markt verschwunden
> sein.
Stimmt auch nicht ganz: Bei den meisten ganz neuen AVRs kann man sich 
die Stack-Initialisierung ebenfalls wiederum sparen, weil der Stack 
Pointer bei einem Reset automatisch initialisiert wird (auf das Ende des 
RAM). Bei der Mega48/88/168-Reihe war das z.B. schon so.
#893762
Lesenswert?

Achja, zum eigentlichen Problem (ohne Deinen Quelltext jetzt gelesen zu 
haben), die Ursache könnte sein:

Du hast in der ISR (ext-Int) eine "Zeitvernichtungsroutine". Du bleibst 
also in der ISR, bis die Zeit abgelaufen ist.

Du hast am ext-Int einen mechanischen Taster. Taster prellen. Wenn 
während der Abarbeitung der ISR der nächste Prellimpuls kommt, wird über 
GIFR ein neuer Interrupt angemeldet, der sofort nach Ende der ISR 
aubgearbeitet wird. Dies erklärt die doppelte Zeit. Als Abhilfe könnte 
man als letzten Befehl der ISR das Interrupt-Flag in GIFR löschen, aber 
so richtig gut wird das auch nicht.

Besser ist es, einre ordentliche Entprellung (im Timer-Interrupt) 
vorzusehen, diesen Timer-Interrupt auch als Basistakt für die 
Verzögerung zu benutzen und die Verzögerung in Software 
herunterzuzählen.

...
OP Persönliche Seite #893779
Lesenswert?

@Hannes

Also Zeit vernichte ich in der INT0-Routine nicht. Aber ne Entprellung 
hab ich tatsächtlich nicht. Ich dachte eben, dass ich die nicht brauche, 
weil ich ja den Interrupt "deaktiviere"...

Also gut, dann werde ich nochmal ein neues Programm schreiben,
ohne Stackinitialisierung
mit Entprellung
und schön Sauber programmiert
Ich stelle es dann hier in den Thread und will wissen, was ich 
bessermachen kann...


Danke!

Gruß Ovular
#893782
Lesenswert?

Hannes Lux wrote:

> Du hast am ext-Int einen mechanischen Taster. Taster prellen. Wenn
> während der Abarbeitung der ISR der nächste Prellimpuls kommt, wird über
> GIFR ein neuer Interrupt angemeldet, der sofort nach Ende der ISR
> aubgearbeitet wird. Dies erklärt die doppelte Zeit. Als Abhilfe könnte
> man als letzten Befehl der ISR das Interrupt-Flag in GIFR löschen, aber
> so richtig gut wird das auch nicht.

Ich würd mal sagen, Du hast den Nagel auf den Kopf getroffen.

Doppelte Zeit riecht penetrant nach fehlender Entprellung.

Warum wird immer gedacht, Entprellung ist nur was für umfangreiche 
Programme?


Peter
OP Persönliche Seite #893798
Lesenswert?

Mooooment!!!

Ich glaub ich verstehe jetzt was ihr denkt...
Aber Ihr solltet euch mal lieber das Programm ansehen.

Doppelte Zeit kann hier eigendlich nicht zustande kommen...
Ich warte ja schließlich außerhalb der Routinen. Wenn innerhalb von 50ms 
nochmal getriggert werden würde, würde der Zähler zwar wieder auf seinem 
Ausganswert stehen, so wie ich ihn eingestellt hab, aber doppelte Zeit?
#893808
Lesenswert?

Steven W. wrote:
> Aber Ihr solltet euch mal lieber das Programm ansehen.

Ist längst geschehen.

> Doppelte Zeit kann hier eigendlich nicht zustande kommen...

Kann sehr wohl.
Du disablest den externen Interupt in sich selbst und enablest ihn erst 
wieder nach Ablauf der Zeit und erst dann kann er ja wieder auf das 
schon ewig gesetzte Pending-Flag hin interrupten.


Peter


P.S.:
Man könnte das uralte Pending-Flag direkt vor der erneuten Freigabe 
setzen, um es zu löschen.
Hilft in diesem konkreten Fall.
Entprellen ist aber besser, hilft in jedem Fall und man muß nie wieder 
daran denken.

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