www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wie viele Cycles darf die Interrupt-Routine haben?


Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin zusammen,

bin gerade dabei die Software RTC von ATMEL zu übernehmen, und stelle 
fest, dass die die ganzen if-Entscheidungen (also ist ++sekunde >60 ...) 
in der Interrupt-Routine haben.
Ist das nicht ungeschickt? - Da wäre es doch besser lieber nur eine FLAG 
zu setzen, welche dann in der while Routine aufgefangen und dann die 
if-Verzweigungen durchforstet... ?

In diesem Zusammenhang wollte ich Fragen, wie viele Cycles eigentlich so 
ne Interrupt-Routine haben sollte. Natürlich so wenig wie geht - doch wo 
hört da der Spaß auf?

Danke Marcel


    if (++t.second==60)        //keep track of time, date, month, and 
year
    {
        t.second=0;
        if (++t.minute==60)
        {
            t.minute=0;
            if (++t.hour==24)
            {
                t.hour=0;
                if (++t.date==32)
                {
                    t.month++;
                    t.date=1;
                }
                else if (t.date==31)
                {
                    if ((t.month==4) || (t.month==6) || (t.month==9) || 
(t.month==11))
                    {
                        t.month++;
                        t.date=1;
                    }
                }
                else if (t.date==30)
                {
                    if(t.month==2)
                    {
                       t.month++;
                       t.date=1;
                    }
                }
                else if (t.date==29)
                {
                    if((t.month==2) && (not_leap()))
                    {
                        t.month++;
                        t.date=1;
                    }
                }
                if (t.month==13)
                {
                    t.month=1;
                    t.year++;
                }
            }
        }
    }

Autor: Hilfs-Sysop (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Soviele dass der Interrupt beendet ist, bevor er erneut auftritt".

In dem Fall hätte die ISR also 60 Sekunden. das mit den vielen ifs darin 
geht also in Ordnung, die sind sowieso nicht besonders aufwändig (=> 
generierte ASM-Sources lesen).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Moin zusammen,
>
> bin gerade dabei die Software RTC von ATMEL zu übernehmen, und stelle
> fest, dass die die ganzen if-Entscheidungen (also ist ++sekunde >60 ...)
> in der Interrupt-Routine haben.
> Ist das nicht ungeschickt?

Von dem ganzen Code wird aber bei der überwiegenden Mehrzahl der Aufrufe 
nur ein verschwindend kleiner Bruchteil ausgeführt.
Und der Rest sind triviale Operationen. Wenn der Compiler das übersetzt 
hast schrumpft das auf vielleicht 15 bis 20 Assembler Operationen 
zusammen.

 - Da wäre es doch besser lieber nur eine FLAG
> zu setzen, welche dann in der while Routine aufgefangen und dann die
> if-Verzweigungen durchforstet... ?

In dem Fall nicht.
Du willst auf keinen Fall haben, dass eine Sekunde verloren geht, weil 
der µC gerade beschäftigt ist. Da soll er lieber ab und an die 15 oder 
20 Instruktionen durchackern und gut ists.
Und wenns alle 4 Jahre, am 28 Februar um Mitternacht, mal ein paar 
µSekunden länger dauert, wird das wahrscheinlich auch kein Beinbruch 
sein. Wenn doch, dann kann man natürlich den kompletten Datums-Teil 
rausziehen und nur diesen über ein JobFlag in der Hauptschleife 
anstossen. In 24 Stunden wird der kleine Racker dann ja doch irgendwann 
Zeit haben, das Datum nachzuziehen.

Autor: Hilfs-Sysop (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Natürlich nur eine Sekunde. Ist trotzdem eine Ewigkeit für den 
µC.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:

> In diesem Zusammenhang wollte ich Fragen, wie viele Cycles eigentlich so
> ne Interrupt-Routine haben sollte.

Es empfiehlt sich, dass ein sekündlich auftrender Interrupt weniger als 
eine Sekunde braucht. ;-)

Wenn dir diese Auskunft zu blöd klingt: Das hängt ganz davon ab, welche 
maximale Latenzzeit deine Anwendung verkraftet. Jedenfalls ist so eine 
ISR durchaus üblich.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hilfs-Sysop schrieb:
> "Soviele dass der Interrupt beendet ist, bevor er erneut auftritt".

Werden eigentlich auch die anderen Interrupts-Flags bei einem Ereignis 
gesetzt, wenn der Controller sich noch in einer anderen 
Interrupt-Routine befinden?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Hilfs-Sysop schrieb:
>> "Soviele dass der Interrupt beendet ist, bevor er erneut auftritt".
>
> Werden eigentlich auch die anderen Interrupts-Flags bei einem Ereignis
> gesetzt, wenn der Controller sich noch in einer anderen
> Interrupt-Routine befinden?

Ja, klar.
Aber die zugehörige ISR wird erst dann ausgeführt, wenn die momentane (+ 
1 Befehl) beendet ist.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Ja, klar.
> Aber die zugehörige ISR wird erst dann ausgeführt, wenn die momentane (+
> 1 Befehl) beendet ist.

Nur, wenn deren Ausfuehrung nicht freigegeben ist.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Supi - vielen Dank an alle

Habt mir wie der Wind geantwortet!

Grüße Marcel

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die Betrachtung ist noch wichtig wie lange not_leap() dauert... ich 
vermute mal nicht so lange aber....

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier nochmla die leap Funktion für die die es interessiert :)

char not_leap(void)      //check for leap year
{
    if (!(t.year%100))
        return (char)(t.year%400);
    else
        return (char)(t.year%4);
}

Sehe gerade, dass hier geteilt wird, ich glaube da ist es einfacher die 
nächten xx Schaltjahre im Klartext zu schreiben als diese Divison Bib 
noch einzubinden

Noch ne Frage meinerseits die nicht ganz in diesen Thread passt:
Ich nutze jetzt nen Timer2 als RTC (OVERFLOW_INTERRUPT). Nun möchte ich 
mit diesem TIMER auch noch einen Taster entprellen. Kann ich ohne 
weiteres das Output-Compare Register beschreiben und dann das 
OUTPUT_COMPARE Interrupt aktivieren oder muss ich erst den momentanen 
Zählerstand speichern, den Timer anhalten, um dann das Output-Compare 
Interrupt und das Register zu setzen/beschreiben und dann wieder den 
Timer starten?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Hier nochmla die leap Funktion für die die es interessiert :)
>
> char not_leap(void)      //check for leap year
> {
>     if (!(t.year%100))
>         return (char)(t.year%400);
>     else
>         return (char)(t.year%4);
> }
>
> Sehe gerade, dass hier geteilt wird, ich glaube da ist es einfacher die
> nächten xx Schaltjahre im Klartext zu schreiben als diese Divison Bib
> noch einzubinden

Wie schon gesagt:
1) tritt der Fall nur alle 4 Jahre auf
2) wenn das tatsächlich ein Problem ist, kann man das ganze 
Datumshochzählen auch in die Hauptschleife (mit Jobflag) auslagern.

> Noch ne Frage meinerseits die nicht ganz in diesen Thread passt:
> Ich nutze jetzt nen Timer2 als RTC (OVERFLOW_INTERRUPT). Nun möchte ich
> mit diesem TIMER auch noch einen Taster entprellen.

Soweit so gut

> Kann ich ohne
> weiteres das Output-Compare Register beschreiben und dann das
> OUTPUT_COMPARE Interrupt aktivieren

Wozu brauchst du den Output Compare?

Tasten entprellen ist zeitlich gesehen ziemlich anspruchslos. Ob du die 
Tasten alle 5ms, oder alle 10ms oder alle 15ms abfrägst, ist Jacke wie 
Hose. Wenn dein Overflow Interrupt so ungefähr in dieser zeitlichen 
Größenordnung aufgerufen wird, dann passt das schon. Das muss nicht 
genau alle 10ms sein.

Gerade beim Tastenentprellen kann man es sich leisten, dass die Zeit 
zwischen zwei Abfragen sich an dem orientiert, was gerade vorhanden ist. 
Kein menschlicher Benutzer dieser Welt kann per Gefühl feststellen ob 
ein Tastendruck jetzt nach 40 oder doch erst nach 60ms zu einer Aktion 
führt.

> Kann ich ohne weiteres das Output-Compare Register beschreiben und
> dann das OUTPUT_COMPARE Interrupt aktivieren

Ja kannst du.

> oder muss ich erst den momentanen Zählerstand speichern,

wozu?
Ein gestoppter Timer verliert nicht seinen Zählerstand.

> den Timer anhalten,

Das willst du eigentlich nicht. Denn dann gehen deiner Uhr Takte 
verloren

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Wozu brauchst du den Output Compare?

Ich bin im Energiesparmodus meines Mikrocontrollers. Wenn der dann durch 
einen PCINT-Interrupt geweckt wird. Wenn der Taster gedrückt wurde, dann 
wird bem Timer Output-Compare aktiviert (µC legt sich wieder schlafen).

Alle 200ms bspweise wird im Output Compare Interrupt geschaut, ob der 
Taster noch gedrückt ist (press_long wenn insgesamt über 5s) oder wenn 
der Taster nicht mehr gedrückt ist (press_short <5s)

Haste da sogar eine bessere Idee?

Grüße
Marcel

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Karl heinz Buchegger schrieb:
>> Wozu brauchst du den Output Compare?
>
> Ich bin im Energiesparmodus meines Mikrocontrollers.

Ah. OK

> Haste da sogar eine bessere Idee?

Vielleicht stell ich mich jetzt blöd an.
Aber du sagtest, du hättest den Timer 2 als RTC benutzt. Ich hab das so 
verstanden, dass du da einen 32kHz Quarz drann hast und du den Overflow 
Interrupt benutzt um die Uhr hochzuzählen.

Korrekt?

Wenn du jetzt aber sowieso den Overflow Interrupt schon am laufen hast, 
dann kannst du ja auch dort im Overflow mal einen Rundumblick auf alle 
Tasten machen und die (natürlich entprellt) auswerten (zb. Danegger 
Entprellung)

Geh ich jetzt von falschen Voraussetzungen aus?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Vielleicht stell ich mich jetzt blöd an.
> Aber du sagtest, du hättest den Timer 2 als RTC benutzt. Ich hab das so
> verstanden, dass du da einen 32kHz Quarz drann hast und du den Overflow
> Interrupt benutzt um die Uhr hochzuzählen.

Ja das ist Korrekt. :)

Klar man kann das einfach in die Routine mit reinbauen, denn Flags 
setzte ich bereits in der PCINT-Routine, dass der Taster gedrückt wurde.

Ne Gute Idee - Der einzige Nachteil wäre doch aber hier, dass der 
Benutzer wenns hart kommt 1Sekunde warten müsste bis der Tasten-Druck 
(entprellt) erkannt würde. (Overflow Interrupt ist sekündlich)

Oder ich mache das anders:
In dem PCINT INTERRUPT wird ja der Pinchange-Interrupt für den Taster 
abgestellt. Den könnte man jetzt wieder in dem Overflow Interrupt an 
stellen. Doch würde auch dies bedeuten, dass der Benutzer max. eine 
Sekunde zwischen 2Tastendrücken warten müsste :(

Hmm - ich glaube da führt kein Weg an dem Output Compare drüber - gerade 
weil ich da auch fest 200ms Abstände einbauen kann und nicht ne 
Schwankung von 0.00001 bis 1.0 Sekunden habe.

oder?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> Karl heinz Buchegger schrieb:
>> Vielleicht stell ich mich jetzt blöd an.
>> Aber du sagtest, du hättest den Timer 2 als RTC benutzt. Ich hab das so
>> verstanden, dass du da einen 32kHz Quarz drann hast und du den Overflow
>> Interrupt benutzt um die Uhr hochzuzählen.
>
> Ja das ist Korrekt. :)
>
> Klar man kann das einfach in die Routine mit reinbauen, denn Flags
> setzte ich bereits in der PCINT-Routine, dass der Taster gedrückt wurde.
>
> Ne Gute Idee - Der einzige Nachteil wäre doch aber hier, dass der
> Benutzer wenns hart kommt 1Sekunde warten müsste bis der Tasten-Druck
> (entprellt) erkannt würde. (Overflow Interrupt ist sekündlich)

OK.
Das wusste ich nicht.
Bin von 32kHZ / 256 = 125Hz
ausgegangen. Alle ~80ms einmal kurz auf die Tasten geschaut reicht ja 
auch aus.

Aber wenn du natürlich die 32kHz mit einem Prescaler auf 256Hz 
runtergebrochen hast, gehts nicht. 1 Sekunde istzu lahm. Da musst du zu 
deinem Gerät eine Flasche Baldrian mit ausliefern.

> Hmm - ich glaube da führt kein Weg an dem Output Compare drüber - gerade
> weil ich da auch fest 200ms Abstände einbauen kann und nicht ne
> Schwankung von 0.00001 bis 1.0 Sekunden habe.

Ja ist ok.
Ich bin von falschen Zahlen ausgegangen.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Da musst du zu
> deinem Gerät eine Flasche Baldrian mit ausliefern

:-D

O.K Dank Dir

Grüße
Marcel

Autor: APW (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Denkanstoss zu deiner RTC-Int als Frage formuliert:

Sperrst du die Interrupts (bzw. zumindest den RTC-Int), wenn du deine 
t-Struktur irgendwo im Hauptprogramm ausliest ?

Nur mal so eine Überlegung zum Restrisiko.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
APW schrieb:
> Sperrst du die Interrupts (bzw. zumindest den RTC-Int), wenn du deine
> t-Struktur irgendwo im Hauptprogramm ausliest ?

Nein bislang noch nicht. - Ist das ratsam?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel schrieb:
> APW schrieb:
>> Sperrst du die Interrupts (bzw. zumindest den RTC-Int), wenn du deine
>> t-Struktur irgendwo im Hauptprogramm ausliest ?
>
> Nein bislang noch nicht. - Ist das ratsam?

Das könnte hilfreich sein
Angenommen es ist 03 Uhr 59 und 59 Sekunden

Du fängst an die Uhrzeit auszulesen
  3 Stunden. gut

Jetzt kommt der Interrupt. Als Folge davon wird die Uhrzeit erhöht. Zu 
4:00:00
Der Interrupt ist beendet und deine Ausleseroutine macht weiter.

  0 Minuten   und 0 Sekunden

Hoppla. Deine Ausleseroutine hat ermittelt, das es jetzt gerade 3:00:00 
ist. Deine in der ISR geführte Uhr sagt aber es sei 4 Uhr!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann das auch ohne Interrupt-Sperre machen. Erst die kleinste 
Einheit lesen, dann den Rest, und hinterher nochmal die kleinste Einheit 
mit dem vorher gelesenen Wert vergleichen. Und das solange wiederholen 
bis es übereinstimmt.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  A. K. (prx)

>Man kann das übrigens auch ohne Interrupt-Sperre machen. Erst die
>kleinste Einheit lesen, dann den Rest, und hinterher nochmal die
>kleinste Einheit mit dem vorher gelesenen Wert vergleichen. Und das
>solange wiederholen bis es passt.

Und was hat man da gewonnen, vor allem im Worst Case? Eine kurze 
Interruptsperre ist sicher und vorhersagbar.

MfG
Falk

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist nur eine Alternative. In diesem Fall hier ist es meistens egal 
was man macht. Es gibt freilich Fälle, wo die Update-Sperre während des 
Auslesens problematisch oder unmöglich ist. Beispielsweise wenn man 
dafür mehrere Hardware-Register ausliest, z.B. einen Timer und seinen 
Prescaler.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Das ist nur eine Alternative. In diesem Fall hier ist es meistens egal
> was man macht. Es gibt freilich Fälle, wo die Update-Sperre während des
> Auslesens problematisch oder unmöglich ist. Beispielsweise wenn man
> dafür mehrere Hardware-Register ausliest, z.B. einen Timer und seinen
> Prescaler.

Hm, da ist die Variante mit dem kurzen sperren der Interrupts aber 
vermutlich einfacher und schneller.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Hoppla. Deine Ausleseroutine hat ermittelt, das es jetzt gerade 3:00:00
> ist. Deine in der ISR geführte Uhr sagt aber es sei 4 Uhr!

Oh mann, Danke A.K. für den Denkanstoß, dass hatte ich gar nicht 
bedacht.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:

> Hm, da ist die Variante mit dem kurzen sperren der Interrupts aber
> vermutlich einfacher und schneller.

Macht kaum einen Unterschied, je nachdem auf aufwendig es ist, die 
Interrupts zu sperren (bei ARM7 sind das beispielsweise mehrere 
Befehle). Und wenn die Werte per Hardware hochgezählt werden, dann hilft 
eine Interrupt-Sperre rein garnichts.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja bei HW Registern gibt es ja meistens eine gewisse Reihenfolge wo 
sowas dann nicht auftritt.
Und genausogut könnte man sage, wenn das incrementierungsintervall im 
gleichen Zeitrahmen wie: Auslesen, Speicher, Auslesen, Vergleichen liegt 
liest du unendlich oft den nächsten Wert ohne zu einem Ergebnis zu 
kommen...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Läubi .. schrieb:

> Naja bei HW Registern gibt es ja meistens eine gewisse Reihenfolge wo
> sowas dann nicht auftritt.

Bei den 16-Bit Timer-Registern einen AVRs ja. Bei Timer/Prescaler eines 
LPC2000 oder STM32 ist mir davon nichts bekannt.

> Und genausogut könnte man sage, wenn das incrementierungsintervall im
> gleichen Zeitrahmen wie:

Ja, das muss man berücksichtigen. In diesem Zeitbereich hat man aber 
ohnehin keine Alternative. Wertebereich überprüfen geht dann.

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.