Interruptabarbeitung

OP #2112181
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
Gast #2112186
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.
Gast #2112189
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.
Gast #2112203
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.
#2112381
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
#2112546
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren