mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Befehle im Interrupt


Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Steven () (ovular) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Anhang

Was ein Käse hier was einzubinden!

Autor: Jochen Müller (taschenbuch)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mhm ja den hab ich wohl vergessen...

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

Autor: Jochen Müller (taschenbuch)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Daniel F. (df311)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jochen Müller (taschenbuch)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Stefan

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

Paradoxisch!

Gruß Ovular

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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. ;-)

...

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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.

...

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Steven () (ovular) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jochen Müller (taschenbuch)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.