Forum: Mikrocontroller und Digitale Elektronik Interruptabarbeitung


von Patrick B. (patrick_b)


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

von codehamster (Gast)


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.

von Helfer (Gast)


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.

von codehamster (Gast)


Lesenswert?

http://www.mikrocontroller.net/articles/Interrupt

Bitte mal durchlesen, könnte hilfreich sein.

von Patrick B. (patrick_b)


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

von Patrick B. (patrick_b)


Lesenswert?

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

Danke

von Helfer (Gast)


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.

von Peter D. (peda)


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

von Martin V. (oldmax)


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
1
   LDS  Reg_A, Time_Ctr_l
2
   ANDI Reg_A, 0b00000001   ; Zeit aktiviert ? z.b. bei Verzögerungszeit 1
3
   BREQ weiter
4
   LDS  Reg_A, Time_Cnt_1    ; Nun den Zähler abwärts zählen
5
   Dec Reg_A
6
   Sts Time_Cnt_1, Reg_A     ;
7
   BRNE weiter               ; wenn nicht 0 dann weiter
8
   LDS  Reg_A, Time_Ctrl     ; Kontrollbyte laden
9
   ANDI Reg_A, 0b11111110    ; Teitzähler sperren
10
   ORI  Reg_A, 0b00000010    ; Flag für Zeit abgelaufen setzen
11
   STS Time_Ctrl, Reg_A      ; und ablegen
12
weiter: ....
Nun ein Ausschnitt aus deiner Programmschleife
1
  LDS Reg_A, Event_Ctrl      ; Event-Control-byte
2
  ANDI Reg_A, 0b00010000     ; irgendeinen Event testen und zuordnen
3
  BREQ Next_Step_1
4
  LDI Reg_A, 10              ; z.B. für eine Verzögerung 10 x ISR
5
  STS  Time_Cnt, Reg_A
6
  LDS Reg_A, Time_Ctrl
7
  ORI Reg_A, 0b00000001      ; Zeitzähler freigeben 
8
  STS Time_Ctrl, Reg_A
9
  LDS Reg_A, Event_Ctrl
10
  ANDI Reg_A, 0b11101111      ; Event quittieren
11
  STS Event_Ctrl, Reg_A
12
Next_Step_1:
13
  LDS  Reg_A, Time_Ctrl
14
  ANDI Reg_A, 0b00000010      ; prüfen, ob Zeit abgelaufen ist 
15
  BREQ Next_Step_2
16
  ; verzögerte Befehle ausführen, evtl. in einer Subroutine (RCall)
17
  LDS  Reg_A, Time_Ctrl
18
  ANDI Reg_A, 0b11111101      ; ausführung quittieren
19
  STS Time_Ctrl, Reg_A        ; und ablegen
20
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

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.