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
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.
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.
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
danke für den Link, habe die Antwort gefunden. Es wird nur das aktuellste Interrupt der gleichen Art abgearbeitet. Danke
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.