Forum: Mikrocontroller und Digitale Elektronik Befehle im Interrupt


von Steven (. (ovular) Benutzerseite


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?

von Steven (. (ovular) Benutzerseite


Angehängte Dateien:

Lesenswert?

Anhang

Was ein Käse hier was einzubinden!

von Jochen M. (taschenbuch)


Lesenswert?

Steven,

Und den Stackpointer willst Du garnicht initialisieren?

Dasd mal als erstes, ohne den Code genau angeschaut zu haben.
Später vielleicht mehr...

Jochen Müller

von Steven (. (ovular) Benutzerseite


Lesenswert?

mhm ja den hab ich wohl vergessen...

AVR-Studio konnte das aber ohne Probleme und Meldungen simulieren...

von Jochen M. (taschenbuch)


Lesenswert?

Vor Dein main: würde ich noch eine vernünftige ORG-Anweisung setzen, so 
liegt Dein Programmstart mitten in den (zwar ungenutzten) Int-Vektoren.
Geht zwar, ist aber nicht sauber so.
Natürlich gehen innerhalb einer Int-Routine ALLE Befehle.

Jochen Müller

von Daniel F. (df311)


Lesenswert?

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.

von Steven (. (ovular) Benutzerseite


Lesenswert?

>Vor Dein main: würde ich noch eine vernünftige ORG-Anweisung setzen

Wie soll diese Anweisung in etwa aussehen?

Dankeschön!

MfG Ovular

von Jochen M. (taschenbuch)


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

von Steven (. (ovular) Benutzerseite


Lesenswert?

Jaja, ich hab das schon verstanden.

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.

Wenn ich mal am Wochenende Zeit hab überleg ich mir mal, wie sich dieses 
fehlerhafte Programm genau verhält.

Gruß Ovular

von Stefan E. (sternst)


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.

von Steven (. (ovular) Benutzerseite


Lesenswert?

@Stefan

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

Paradoxisch!

Gruß Ovular

von Hannes L. (hannes)


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

...

von yalu (Gast)


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.

von Johannes M. (johnny-m)


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.

von Hannes L. (hannes)


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.

...

von Steven (. (ovular) Benutzerseite


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

von Peter D. (peda)


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

von Steven (. (ovular) Benutzerseite


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?

von Peter D. (peda)


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.

von Steven (. (ovular) Benutzerseite


Lesenswert?

Achso ja jetzt!

Sorry ich dachte der nächste Interrupt kommt schon nach der INT0-Routine 
zustande. Okok! Eigendlich ja logisch... Naja

Also ich teste das nochmal

Gruß Ovular

von Jochen M. (taschenbuch)


Lesenswert?

> Jochen Müller ist in seinem ersten Beitrag einem Irrtum erlegen.

Oh je... Das stimmt.
Wenn man wie ich, ständig mit den grossen AVR arbeitet,
hält man sowas intuitiv für nicht vorstellbar,
dass der keinen wirklichen Stack hat.

Also: Immer schön das Datenblatt lesen!

Jochen Müller

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.