mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interruptabarbeitung


Autor: Patrick B. (patrick_b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

angenommen ich habe ein Interrupt das alle 10ms ausgelöst wird. Ich 
programmiere nun mehrere delays in mein Programm, sagen wir 100ms. In 
diesen 100ms kommt dann ca 10 mal das Interrupt herein. Werden nach 
diesen 100ms dann alle diese 10 Interrupts der gleichen Art bearbeitet 
oder nur das das aktuellste?

Danke

Autor: codehamster (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Patrick,
ein Interrupt unterbricht dein Programm, also auch deinen delay. Sobald 
die Interruptroutine abgearbeitet ist wird wieder an der selben stelle 
weiter gearbeitet. Somit werden nach dem ablauf deines Delays nicht 10 
interrupts ausgeführt.

Anders sieht es aus wenn du den delay in der Interruptroutine hast.

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Softwaredelay im Anwendungsprogramm? Die Interrupts werden während 
deines 100ms Delays abgearbeitet. Dein 100ms Delay ist deswegen kein 
100ms Delay, sondern um bis zu '10 mal Laufzeit der Interruptroutine' 
länger.

Autor: codehamster (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.mikrocontroller.net/articles/Interrupt

Bitte mal durchlesen, könnte hilfreich sein.

Autor: Patrick B. (patrick_b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok wie schaut es aus wenn ich den 100ms delay in einem Interrupt 
programmieren würde und währendessen 10 mal ein gleicher anderer 
Interrupt eintritt. Werden alle 10 bearbeitet oder nur der akteuellste?

Danke

Autor: Patrick B. (patrick_b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für den Link, habe die Antwort gefunden. Es wird nur das 
aktuellste Interrupt der gleichen Art abgearbeitet.

Danke

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist im Datenblatt des µC nachzulesen.

Bei der AVR Familie: Es wird ein Interrupt-Ereignis einer 
Interruptquelle (Timer, ADC, externer Interrupt, Watchdog usw.) gemerkt 
und nach dem Zurücksetzen des Interruptbits des aktuellen Interrupts 
(beim RETI aus der ISR) ausgeführt. Weitere IRQ-Ereignisse der gleichen 
Interruptquelle gehen verloren. Bei mehreren gemerkten Interrupts aus 
verschiedenen Interruptquellen werden die in einer festen Reihenfolge 
abgearbeitet.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick B. schrieb:
> ok wie schaut es aus wenn ich den 100ms delay in einem Interrupt
> programmieren würde

Delays in Interrupts werden streng bestraft.
Und auch im Main machen solche extrem langen Monsterdelays Probleme.
Daher nur bei sehr kleinen Programmen oder zu Debugzwecken verwenden.

100ms sind 2.000.000 Zyklen [20MHz]. Zähl mal bis 2.000.000, dann weißt 
Du, wie die CPU sich dabei fühlt.


Peter

Autor: Martin Vogel (oldmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
Wofür brauchst du Delays ? Du hast doch eine ISR, die alle 10 mSek. 
aufgerufen wird. Bau deine Zeitverzögerung in die ISR, dann ist sie 1. 
immer zuverlässig so lang wie du möchtest und 2. behindert sie nicht 
dein Programm. Also, du möchtest beim Eintreten einer Bedingung  nach 
100 mSek. etwas anderes machen. Also setzt du eine Variable als Zähler 
ein, setzt sie auf 10 und läßt sie herunterzählen. Erreicht sie eine 0, 
führst du deinen Programmteil aus. Zusätzlich brauchst du noch ein Bit, 
um die aktivierte Zeitverzögerung anzuzeigen.
In Assembler funktioniert es etwa so:
Die Zeitvariable für Verögerung nenne ich mal Time_Cnt_x, dazu kommt ein 
Event_Ctrl, für ein aufgetretenes Ereignis, z.B.einen Tastendruck oder 
eine Anzeige für ein abgearbeitetes Programm und natürlich ein 
time_Ctrl, um die aktivierte Verzögerungszeit anzuteigen.
Zuerst ein Ausschnit aus der Timer-ISR
   LDS  Reg_A, Time_Ctr_l
   ANDI Reg_A, 0b00000001   ; Zeit aktiviert ? z.b. bei Verzögerungszeit 1
   BREQ weiter
   LDS  Reg_A, Time_Cnt_1    ; Nun den Zähler abwärts zählen
   Dec Reg_A
   Sts Time_Cnt_1, Reg_A     ;
   BRNE weiter               ; wenn nicht 0 dann weiter
   LDS  Reg_A, Time_Ctrl     ; Kontrollbyte laden
   ANDI Reg_A, 0b11111110    ; Teitzähler sperren
   ORI  Reg_A, 0b00000010    ; Flag für Zeit abgelaufen setzen
   STS Time_Ctrl, Reg_A      ; und ablegen
weiter: ....
Nun ein Ausschnitt aus deiner Programmschleife
  LDS Reg_A, Event_Ctrl      ; Event-Control-byte
  ANDI Reg_A, 0b00010000     ; irgendeinen Event testen und zuordnen
  BREQ Next_Step_1
  LDI Reg_A, 10              ; z.B. für eine Verzögerung 10 x ISR
  STS  Time_Cnt, Reg_A
  LDS Reg_A, Time_Ctrl
  ORI Reg_A, 0b00000001      ; Zeitzähler freigeben 
  STS Time_Ctrl, Reg_A
  LDS Reg_A, Event_Ctrl
  ANDI Reg_A, 0b11101111      ; Event quittieren
  STS Event_Ctrl, Reg_A
Next_Step_1:
  LDS  Reg_A, Time_Ctrl
  ANDI Reg_A, 0b00000010      ; prüfen, ob Zeit abgelaufen ist 
  BREQ Next_Step_2
  ; verzögerte Befehle ausführen, evtl. in einer Subroutine (RCall)
  LDS  Reg_A, Time_Ctrl
  ANDI Reg_A, 0b11111101      ; ausführung quittieren
  STS Time_Ctrl, Reg_A        ; und ablegen
Next_Step_2:  ......
Wie du siehst, wird dein Hauptprogramm nicht mehr durch Delays 
aufgehalten und bleibt flott unterwegs. Der Hintergund:
Du hast Eingänge, die bspw. einen Tastendruck oder ein Signal erfassen 
müssen. Normalerweise reicht es, wenn am Anfang der Programmschleife die 
IO's abgefragt werden. Hast du nun Delays in diese Programmschleife, 
verändert sich die Zykluszeit und du mußt dafür sorgen, durch 
entsprechend lange Tastenbetätigung z.B. das deine Eingabe auch erfasst 
wird. Manch einer kommt da sogar auf die Idee und "opfert" 
interruptfähige Eingänge. Dies ist aber der falsche Ansatz. Gewöhn dir 
die Verwendung von Delais gar nicht erst an und bau dir deine 
Zeitabhängigen Funktionen in eine Timer ISR. Sicherlich anfangs etwas 
gewöhnungsbedürftig, aber danach wird man die Delais auch nicht mehr 
brauchen.

Gruß oldmax

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.