Forum: Mikrocontroller und Digitale Elektronik Interrupt mit Bascom wird doppelt ausgeführt


von Bark (Gast)


Lesenswert?

Hallo,

ähnlich wie hier:
Beitrag "mega32 interrupt zählt doppelt"

habe ich das Problem, dass ein prellender Taster unter bascom eine 
doppelte Ausführung meiner ISR verursacht. Wie kann ich in Bascom am 
Ende der ISR es so einstellen, dass alle noch wartenden Interrupts 
gelöscht werden? Hier mal mein quick&dirty sourcecode:

$regfile = "m48def.dat"                                     'compile for 
mega48
$crystal = 10000000                                         'make sure 
it uses the external 10 MHz crystal oscillator
                                                             'dont 
forget to set fusebits


Config Portc = Output
Config Portd = Input
Config Portb = Input

Portc = 0                                                   'no signal 
at output

Portb = 255
Portd = 255                                                 'Pullups

Declare Sub Inter

On Int0 Inter
On Int1 Inter


Enable Int0                                                 'enables the 
TIMER1 interrupt
Enable Int1
Config Int0 = Falling                                       'trigger on 
falling edge
Config Int1 = Falling

Enable Interrupts                                           'allow 
interrupts to be set

Dim C As Byte                                               'set counter 
variable


Do                                                          'main loop 
is empty

Loop

End


Inter:                                                      'interrupt 
routine
Disable Int0                                                'prevent 
double triggering
For C = 1 To 10                                             '100 images
  Portc.0 = 1                                               'set camera 
pin high
  Waitms 49                                                 'wait a 
moment
  Portc.0 = 0                                               'set low
  Waitus 1000                                               'allow 
readout
Next C

Enable Int0                                                 're-enable 
trigger

Return

von Bark (Gast)


Lesenswert?

$regfile = "m48def.dat"       'compile for mega48
$crystal = 10000000

Config Portc = Output
Config Portd = Input
Config Portb = Input

Portc = 0

Portb = 255
Portd = 255  'Pullups

Declare Sub Inter

On Int0 Inter
On Int1 Inter


Enable Int0      'enables the TIMER1 interrupt
Enable Int1
Config Int0 = Falling   'trigger on falling edge
Config Int1 = Falling

Enable Interrupts    'allow interrupts to be set

Dim C As Byte   'set counter variable


Do       'main loop is empty

Loop

End


Inter:   'interrupt routine
Disable Int0       'prevent double triggering
For C = 1 To 10    '100 images
  Portc.0 = 1        'set camera pin high
  Waitms 49 'wait a moment
  Portc.0 = 0    'set low
  Waitus 1000 'allow readout
Next C

von Peter D. (peda)


Lesenswert?

Bark schrieb:
> habe ich das Problem, dass ein prellender Taster unter bascom eine
> doppelte Ausführung meiner ISR verursacht.

Das ist völlig normal, wenn man nen externen Interrupt nimmt, d.h. 
Bascom ist daran unschuldig.

Die beste Methode ist, keinen externen Interrupt zu nehmen.

Die quick& wirklich sehr sehr dirty Methode ist, im Interrupt erstmal 
elendig lange kostbare CPU-Zeit zu verwarten und am Ende das 
Interrupt-Pending-Flag zu löschen, indem man es setzt.


Peter

von Bark (Gast)


Lesenswert?

Danke für die Antwort, aber ich brauche unbedingt einen externen 
Interrupt, und der darf auf keinen Fall doppelt getriggert werden. Zeit 
verwarten ist gar kein Problem, solange das reproduzierbar ist, ist es 
egal. Kannst Du mir sagen, wie ich das Interrupt Pending Flag setzen 
kann?

von Klaus D. (kolisson)


Lesenswert?

hallo bark,

ich habe das in bascom bisher so gelöst:

int auf falling,
interner pullup am int-eingang einschalten
100nF vom inteingang nach masse


in der isr frage ich dann nochmal den portpin direkt ab, ob er auf null 
liegt.
wenn das so ist, setze ich das flag  "taste gedrückt", welches dann in 
der hauptschleife verarbeitet wird.

hat bisher ganz gut geklappt.

natürlich gibt es auch die verschiedenen qualitäten von tastern zu 
bedenken.

wenn das alles nicht hilft, müsstest du vielleicht zusätzliche hardware 
bemühen, um den taster  zu entprellen.

siehe z.b. http://www.labbookpages.co.uk/electronics/debounce.html

gruss  klaus

von Joachim R. (bastelbaer)


Lesenswert?

Hi nehm deine Routine aus dem Interrupt raus und mach es so wie Klaus 
schrieb. Also einfach in der Art:

Interrupt auf Falling mit internem Pull-Up und Taster gegen Masse

Do       'main loop is empty
  if Tasterflag=1 Then
    For C = 1 To 10    '100 images
      Portc.0 = 1        'set camera pin high
      Waitms 49 'wait a moment
      Portc.0 = 0    'set low
      Waitus 1000 'allow readout
    Next C
    Tasterflag=0
  end if
Loop

End


Inter:   'interrupt routine
  Tasterflag=1
Return

Dann ist es egal wie oft dein Interrupt kommt. Solange das Tasterflag 
nicht zurückgesetzt wird, hat das keine Auswirkung auf den Ablauf des 
Programmes.
Und wenn die Taster entprellen willst, dann einfach per Software und 
ohne INT0/1-Interrupt sondern mit Timerinterrupt. Aber dann hast du xx 
Millisekunden, bis du definiert sagen kannst ob der Taster wirklich 
gedrückt ist oder nur ein Störimpuls die Eingabe triggert.

von Wah (Gast)


Lesenswert?

Hmm, das wäre eine Möglichkeit, ich habe auch das hier probiert:

GIFR.INTF0 = 1

Nur dann meckert Bacom "falscher Datentyp".Wieso? Kann ich das GIFR 
Register nicht beschreiben oder was?

Set Intf0

Hingegen geht, scheint aber keinerlei Auswirkungen auf den 
versehentlichen doppelten Interrupt zu haben.

von frag (Gast)


Lesenswert?

Du kannst auch am den anfang der ISR das Prellen abwarten:

Inter:
   waitms 20
   if int0=1 then reti 'weg hier falls es nur eine Nadel war

   ...
return

von hmm.... (Gast)


Lesenswert?

Ich mach die Tasten mit einem timer. In einem vom timertick ausgeloesten 
Prozess schau ich ob eine Taste gedrueckt wurde. Eine Taste wir erst als 
gedrueckt/losgelassen akzeptiert wenn der Zustand zwei mal gleich ist.

von Joachim R. (bastelbaer)


Lesenswert?

Interruptroutinen die zuviel innerhalb der eigenen Routine machen, 
sollte man vermeiden, da sonst u.U. die Routine mehrfach aufgerufen 
werden kann was zu einem Stacküberlauf führen kann. Wenn z.B. in der 
Routine von "frag" während der Wartezeit von 20ms Interrupts kommen, 
wird die Routine mehrfach aufgerufen und Overflow ist da. Besser in den 
ISR-Routinen nur "Kleinkram" machen und die Zeitschleifen die du z.B. 
hast ins normale Hauptprogramm auslagern.

Hier mal was zum Entprellen von bis zu acht Tastern an einem Port in 
BASCOM. Ist eine Portierung eines C-Quelltextes der hier im Forum 
gepostet wurde.

Die Variable io_press zeigt bitweise dass ein Eingang ein Signal 
hat/hatte. Das liest man aus und löscht dann die Variable. Die Variable 
io_state gibt den aktuellen Zustand der Eingänge an. Die Variablen 
io_ct0 und io_ct1 bilden einen Zähler bis drei für jedes Bit des 
Eingangsport. Die Entprell-ISR-Routine ist wirklich tricky gemacht und 
funzt einwandfrei.
Der Timerwert von hier 100 gibt an wie oft die Routine die Eingänge 
checkt.
1
'Variablen für die Entprell-Routine
2
Io_port Alias Porta
3
Io_pins Alias Pina
4
Config Io_port = Input
5
Io_port = 255 ' Pull-Ups setzen
6
Dim Iwr0 As Byte
7
Dim Io_ct0 As Byte
8
Dim Io_ct1 As Byte
9
Dim Io_state As Byte
10
Dim Io_press As Byte
11
12
' Init Eingänge
13
Io_ct0 = 0
14
Io_ct1 = 0
15
Decr Io_ct0
16
Io_ct1 = Io_ct0
17
Io_state = 0
18
Io_press = 0
19
20
'Timer2-Interrupt konfigurieren (Timer2 = 8bit)
21
Config Timer2 = Timer , Prescale = 1024
22
On Timer2 Timer2_isr              'Interrupt Service Routine anspringen
23
Timer2 = 100
24
Enable Timer2
25
26
' Interrupts freigeben
27
Enable Interrupts
28
29
'### MAINLOOP
30
Do
31
32
  ' Zum Keyboardcheck den Timer anhalten
33
  Disable Timer2
34
  If io_press<>0 Then
35
    if io_press.0=1 Then 'tu was
36
    if io_press.1=1 Then 'tu was andres
37
    io_press=0
38
  End If
39
  Enable Timer2 ' und wieder starten
40
Loop
41
END
42
43
'### Interrupt Routine für Timer2 (Eingänge pollen + entprellen)
44
Timer2_isr:
45
  Timer2 = 100
46
  Iwr0 = Io_pins
47
  Iwr0 = Not Iwr0
48
  Iwr0 = Iwr0 Xor Io_state
49
  Io_ct0 = Io_ct0 And Iwr0
50
  Io_ct1 = Io_ct1 And Iwr0
51
  Io_ct0 = Not Io_ct0
52
  Io_ct1 = Io_ct1 Xor Io_ct0
53
  Iwr0 = Iwr0 And Io_ct0
54
  Iwr0 = Iwr0 And Io_ct1
55
  Io_state = Io_state Xor Iwr0
56
  Iwr0 = Iwr0 And Io_state
57
  Io_press = Io_press Or Iwr0
58
59
Return

von Bark (Gast)


Lesenswert?

Jepp, ok, jetzt läuft die Aufgabe in der Hauptroutine und es 
funktioniert super und ohne jedes Problem. Dankeschön!

von krümeltee (Gast)


Lesenswert?

Wäre es nicht auch möglich am Anfang der ISR die Interrupts komplett zu 
deaktivieren oder nur den einen Interrupt und dann am Ende wieder 
einzuschalten?

Ich habe vor kurzem beim Kennenlernen der 8051er einen Counter mit dem 
Timer gebastelt, der das Ergebnis dann noch bearbeitet und auf 7 Segment 
Anzeigen ausgibt. Das ist relativ zeitaufwendig und es hat auch 
rumgesponnen wenn der Impuls zu oft kam. Ich habe dann einfach die Ints 
ausgemacht am Anfang der ISR und am Ende wieder an. So können zwar 
Ereignisse unterschlagen werden, aber wenn es darauf nicht ankommt, 
passt das auch.

von Peter D. (peda)


Lesenswert?

krümeltee schrieb:
> Wäre es nicht auch möglich am Anfang der ISR die Interrupts komplett zu
> deaktivieren oder nur den einen Interrupt und dann am Ende wieder
> einzuschalten?

Du vertraust der Hardware wohl nicht?
Da muß ich Dich enttäuschen, sie macht das automatisch, genau dem 
Datenblatt entsprechend.



> Ich habe vor kurzem beim Kennenlernen der 8051er einen Counter mit dem
> Timer gebastelt, der das Ergebnis dann noch bearbeitet und auf 7 Segment
> Anzeigen ausgibt. Das ist relativ zeitaufwendig und es hat auch
> rumgesponnen wenn der Impuls zu oft kam. Ich habe dann einfach die Ints
> ausgemacht am Anfang der ISR und am Ende wieder an.

Das ist Quatsch mit Soße.

Die einzige Möglichkeit, daß beim 8051 ein Interrupt sich selber 
unterbricht, ist die, daß Du im Interrupthandler die eigene Priorität 
hochsetzt.
Ansonsten kannst Du Dich auf den Kopf stellen, erst nach dem RETI kann 
der nächste Interrupt zuschlagen.
Man sollte ruhig mal das Datenblatt lesen, bevor man völlig sinnlosen 
und wirkungslosen Code in den Interrupt packt.


Wenn Du aber nem anderen Interrupt ne höhere Priorität zugewiesen hast 
und der stört, dann kann man die Interrupts global sperren.
Dann fragt sich allerdings, warum man diesen überhaupt erst die höhere 
Priorität gegeben hat, um sie dann doch wieder auszuhebeln.

Machs also lieber gleich richtig, d.h. nutze die Prioritäten erst dann, 
wenn Du Dir dabei auch was gedacht hast.


Peter

von Alex (Gast)


Lesenswert?

Hallo,

ja, der Beitrag ist schon sehr alt. Ich stand jetzt aber vor dem 
gleichem Problem einen weiteren Interrupt innerhalb der ISR zu sperren 
oder eine doppelte Auslösung zu verhindern. Vielleicht hilft es ja 
jemandem.

User "Wah" hat eigentlich schon die richtige Lösung gepostet:

"GIFR.INTF0 = 1"

Keine Ahnung warum bei ihm eine Fehlermeldung kam...

GIFR ist das "general interrupt flag register", sowas wie ein 
Zwischenspeicher der weitere Interrupts auch innerhalb der ISR 
speichert.
Ist die ISR am Ende bei Return angekommen, wird zwar wieder in das 
Hauptprogramm gesprungen, aber der zwischengespeicherte Interrupt 
wieder sofort ausgelöst.

Ein DISABLE der Interrupts innerhalb der ISR funktioniert leider nicht 
und scheint auch nicht nötig zu sein, da der AVR zwar weitere Interrupts 
sperrt, aber eben das FLAG für einen Interrupt im GIFR speichert. Ein 
weiteres Interrupt wird dann eben nur zeitversetzt ausgelöst, sobald man 
z.B. im Hauptprogramm wieder die Interrupts auf ENABLE setzt.

Man muss also innerhalb der ISR den Interrupt Flag im GIFR Register 
löschen und zwar ganz am Ende vor Return.

Das GIFR hat 8 Bits, relevant für INT0 & INT1 sind Bit6 und Bit7.
Man setzt nun einfach das entsprechende Bit des Registers auf 1.

Möchte man den Interrupt Flag für INT0 löschen:
GIFR = 64

Möchte man den Interrupt Flag für INT1 löschen:
GIFR = 128

Natürlich geht das auch mit binärer Schreibweise.
Für INT0:
GIFR = &b10000000

Für INT1:
GIFR = &b01000000

So könnte das in Bascom aussehen:

On_int:
Portd = &B00000000
Sound Portd.7 , 200 , 1000
Wait 5
Gifr.int1 = 1
Return

Alex

von Fred R. (fredylich)


Lesenswert?

Hallo Alex,

eine sehr, sehr hilfreiche Erklärung.
Mit Interrupt’s hatte ich auch immer wieder Probleme. Seit dem ich am 
Anfang der Hauptschleife das GIFR- Register komplett lösche nicht mehr. 
War oft ein Problem für Stacküberlauf.
Eins ist für mich noch unklar warum Interrupt in eine Art 
„Schieberegister“  sich die „Klicks" merken müssen.
Ist es nicht so, INTx  spring aus der Do in ISR. Nun eine Entscheidung 
treffen und wieder ab zu Do.
Warum diesen „Klick“ merken und dummer Weise den letzten „Klick“ wieder 
an Anfang des Register stellen, wenn Überlauf?


Mit freundlichen Grüßen

von pfeife (Gast)


Lesenswert?

Fred R. schrieb:
> Eins ist für mich noch unklar warum Interrupt in eine Art
> „Schieberegister“  sich die „Klicks" merken müssen.

Nicht nur das ist mir auch unklar.


> Ist es nicht so, INTx  spring aus der Do in ISR. Nun eine Entscheidung
> treffen und wieder ab zu Do.
> Warum diesen „Klick“ merken und dummer Weise den letzten „Klick“ wieder
> an Anfang des Register stellen, wenn Überlauf?

Jau. Entscheidung und ab ... Aber was sind die „Klicks" vom 
„Schieberegister“

von Staubfänger (Gast)


Lesenswert?

Wenn ich Dich recht verstehe, dann fragst Du Dich warum der uC so 
funktioniert, daß ein Interrupt mehrfach ausgelöst werden kann; 
insbesondere warum er noch einmal ausgelöst werden kann, wenn der erste 
doch gerade behandelt wird bzw. eben behandelt wurde.

Zu dem folgenden schaue Dir bitte mal parallel die Bilder und die 
Beschreibung im Datenblatt an:

Das Verhalten ergibt sich zunächst einmal ganz natürlich, wenn man eine 
ganz einfache Schaltung dafür entwirft:
Das externe Signal löst einen Interrupt dadurch aus, das ein Bit in 
einem Register gesetzt wird.
Bei jedem Übergang von einem Befehl zum nächsten, beeinflusst diese Bit, 
wenn es gesetzt wurde, welcher Befehl als nächstes ausgeführt wird; 
effektiv in dem der Programmzähler auf einen, von dem Interrupt 
abhängigen Wert gesetzt wird. Das ist bei den AVRs eine Adresse in der 
Interrupt-Vektor-Tabelle.
Gleichzeitig wird das oben erwähnte Bit, das anzeigt, dass ein Interrupt 
ausgelöst wurde, wieder zurückgesetzt. (Das könnte man auch zu einem 
anderen Zeitpunkt machen, aber das hängt von dem Hersteller ab, wie er 
sich da entscheidet).
Tritt also das Ereignis, das diesen Interrupt auslöst, nach diesem 
Zeitpunkt noch einmal ein, so wird das Bit wieder gesetzt.
Der Mechanismus, der nach jedem Befehl, das Interrupt-Bit berücksichtig, 
ist allerdings zu diesem Zeitpunkt ausser Kraft gesetzt, sonst würde 
eine gerade laufender ISR unterbrochen. (Bei manchen CPUs wird das auch 
nicht getan oder nur für den zuletzt ausgelösten Interrupt. Hängt wieder 
vom Hersteller ab und diese Varianten bieten auch gewisse Vorteile).
Jedenfalls, da der Mechanismus ausser Kraft ist, wird die ISR nicht 
unterbrochen.
Erst wenn man mit IRET die ISR verlässt, wird er wieder wirksam. Falls 
inzwischen wirklich der Interrupt erneut aufgetreten ist, so wird gleich 
wieder die entsprechende ISR ausgeführt.

Wie gesagt, das Verhalten ergibt sich zwangsläufig aus einer ganz 
einfachen, man könnte sagen Straight-Forward oder As-Simple-As-Possible 
Implementierung dieses Ablaufs. Das ist insofern keine "Absicht".
Diese, wie auch die anderen oben in Klammern erwähnten Varianten sind 
sinnvoll nutzbar.

Man muss aber doch wissen, was bei einem gewissen Prozessor tatsächlich 
geschieht und das berücksichtigen.

Bei Tastern nun, ist es so, dass die, wie Du schon weißt, prellen. Das 
aber bedeutet, dass ein Interrupt wahrscheinlich mehrfach ausgelöst 
wird.
Es gibt nun zwei Auswege aus dieser Situation:

A) Man betreibt prellende Taster gar nicht an einem Interrupt. Da spart 
man sich zusätzlichen Code um diesen Fall zu behandeln.

B) Man fügt zusätzlichen Code hinzu, um den Fall zu behandeln - d.h. 
kurz hintereinander auftretende gleiche Interrupts als einen zu 
behandeln. Das führt aber das Problem ein, dass man ziemlich genau 
wissen muss, welche Interrupts durch die selbe Ursache (den einen und 
einzigen Tastendruck) ausgelöst wurden und welche nicht. Das ist nicht 
ganz einfach, denn die Taster verhalten sich verschieden, andererseits, 
kann ein Benutzer kaum in kürzeren Abständen, als etwa ein paar 100ms 
eine Taste drücken.

Deswegen vermeidet man, und rät insbesondere Anfängern, Taster nicht mit 
Interrupts zu behandeln.

Andererseits gibt es durchaus Interruptquellen, die so kurz 
hintereinander Interrupts auslösen, das die ISR noch nicht fertig werden 
konnte. Auch dafür gibt es einige Wege zu Behandlung, von denen eine 
ist, den oben beschriebenen Ablauf nicht als Problem, sondern als Lösung 
zu betrachten:
Wenn nämlich ein weiterer Interrupt wiederum das Flag setzt, und man 
weiß, dass das so sein soll, dann kann man das nutzen. Da aber nur noch 
ein zusätzlicher Interrupt gespeichert werden kann, geht das nur mit 
Quellen, die während der Laufzeit der ISR höchstens einen weiteren 
Interrupt auslösen. Geht also auch nicht für alle Fälle.

Da guckt man dann, danach die ISR zu verkürzen, damit man im Code auch 
alle Interrupts mitbekommt.

Das ist ein komplexes Thema. Daher wird Anfängern zuerst dazu geraten:
1. ISR so kurz wie möglich zu halten.
2. Keine Quellen an Interrupts zu betreiben die unnötige weitere 
Interrupts auslösen - wie es eben bei Tastern der Fall ist.

Ich hoffe das hilft Dir.

von Peter D. (peda)


Lesenswert?

Staubfänger schrieb:
> Wie gesagt, das Verhalten ergibt sich zwangsläufig aus einer ganz
> einfachen, man könnte sagen Straight-Forward oder As-Simple-As-Possible
> Implementierung dieses Ablaufs. Das ist insofern keine "Absicht".

Das Verhalten ist sehr wohl volle Absicht!
Jeder Interrupt ist zwangsläufig wichtig, sonst würde man ja keinen 
Interrupt verwenden.
Oberste Prämisse ist daher, es darf kein Interrupt verloren gehen, auch 
wenn er gerade nicht behandelt werden kann.
Z.B. ein Ethernet-Controller kann mehrere Interruptquellen haben und 
jede muß behandelt werden, sonst gehen Nachrichten verloren.

Daß man Interrupts auch für schneckenlahme menschliche Eingaben mit 
prellenden Tastern verwendet, ist zwar prinzipiell erlaubt, aber nicht 
die Regel (sollte es nicht sein).

von Staubfänger (Gast)


Lesenswert?

Peter D. schrieb:
> Staubfänger schrieb:
>> Wie gesagt, das Verhalten ergibt sich zwangsläufig aus einer ganz
>> einfachen, man könnte sagen Straight-Forward oder As-Simple-As-Possible
>> Implementierung dieses Ablaufs. Das ist insofern keine "Absicht".
>
> Das Verhalten ist sehr wohl volle Absicht!

Da das von Dir, meinem Zitat folgende, beschriebene ohne Zweifel 
plausibel ist, hätte ich wohl besser gar keine Vermutung darüber äussern 
sollen, die sich wie eine definitive Aussage liest. Ich ziehe sie daher 
zurück. Was da wer und wann gedacht hat, bleibt vermutlich ohnehin auf 
immer im Dunklen.

Es scheint mir im übrigen durchaus nicht unwahrscheinlich, dass 
derjenige, der das zum ersten Mal implementiert hat, dies auf die von 
mir beschriebene Weise getan hat und beim Testen erfreut festgestellt 
hat, dass er alleine durch das löschen des Interrupt-Flags, einen (nur 
einen) weiteren Interrupt erfassen kann, obwohl die ISR schon läuft. 
Aber ich will nicht darauf bestehen, das wäre albern.

Andererseits ist der von Dir beschriebenen Maxime auch nicht vollständig 
entsprochen worden, denn spätestens der dritte Interrupt geht ja - in 
der beschriebenen Implementierung - fallweise doch verloren. Ist das 
nun, für sich genommen, ein Zeichen, dass er das gewollt hat? Oder hat 
er es hingenommen? Wenn ja, warum nicht auch die erste Eigenschaft?
Er konnte allenfalls annehmen, das in der Praxis ein weiterer Interrupt 
reichen sollte. Das das oft nicht der Fall ist, zeigen aber meiner 
Meinung nach Mechanismen die mehrfach ausgelöst Interrupts zulassen 
(z.B. im Verein mit reentranten ISRs.

Ich habe ja keinesfalls verneint, dass potentiell jeder Interrupt 
wichtig ist. Auch liest sich mein Text, meiner Meinung nach, keinesfalls 
so, als wenn ich mit der Beschreibung des Ablaufs sagen wollte, das dies 
der einzig sinnvolle ist, oder der, der alle denkbaren Anforderungen 
erfüllt.
Sie zielte vielmehr auf den Fokus der Frage. Der war nicht, warum alle 
Interrupts erfasst werden (was ohnehin nicht der Fall ist; jedenfalls 
nicht unter gewissen weiteren Nebenbedingungen) sondern vielmehr, warum 
denn mehr als einer erfasst wird, in dem Kontext von Tastern, wo doch 
die nachfolgenden Interrupts (durch das prellen) so störend sind.

Naja. Ich bemühe mich hier, klarzustellen, dass ich nicht völligen 
Unsinn erzählt habe. Ich weiß; Du bist in der Regel keiner der unbedingt 
Recht haben will. Ich bin da sensibler als Du. Aber was soll's? Es 
sollte dem TO helfen ein Verständnis zu entwickeln.

von Staubfänger (Gast)


Lesenswert?

@ Peter D.

Wenn ich mir das recht überlege, dann wäre es besser gewesen, als 
primäres Ziel zunächst das zu nennen, was Du, Peter, genannt hast: 
Nämlich das, möglichst viele, wenn nicht alle Interrupts erfasst werden 
sollen. Und dass das eben auch zur Folge hat, dass gerade bei Tastern 
unnötig viele Interrupts erfasst werden. Und dass das wiederum zu dem 
Ratschlag führt, Taster nicht mittels Interrupts zu erfassen.

Also gut: Bark, bitte fasse meinen Beitrag in diesem Lichte auf. Ich 
hoffe ich habe Dich nicht allzusehr in die Irre geführt.

von Alex (Gast)


Lesenswert?

Hallo Fred,

freut mich, dass Dir meine Erklärung gefällt. Ich suche selbst immer 
wieder nach möglichst einfachen Erklärungen mit expliten Anleitungen und 
kleinen Beispielen. Oft reichen MIR pauschale Aussagen wie "Flag 
löschen" nicht aus.Besonders immer dann, wenn ich ungeduldig mal etwas 
Neues ausprobieren möchte, und das Datenblatt irgendwie wieder viel zu 
lang und kryptisch ist. Diesmal habe ich mich eben durchgebissen und der 
kleine Artikel ist halt 7 Jahre nach Fragestellung entstanden :-)

"Eins ist für mich noch unklar warum Interrupt in eine Art
„Schieberegister“  sich die „Klicks" merken müssen."

Eine Ausführliche Antwort hast Du ja mittlerweile erhalten :-) Hatte mir 
darüber noch keine Gedanken gemacht, aber war ein interessanter Ausflug 
noch ein Stück tiefer in die Hardware hinein.

Mich als reinen Anwender der nur ganz simplen Code mit Bascom und ganz 
wenig in Assembler schreibt, hat dieses Verhalten des AVR`s eigentlich 
auch immer eher gestört. Aber: "it`s a feature, not a bug" Also klasse, 
dass Du mit Deiner Frage die Diskussion darüber ausgelöst hast. Vielen 
Dank auch an die nachfolgenden User für die interessanten Erklärungen.

Alex

von Peter D. (peda)


Lesenswert?

Staubfänger schrieb:
> Andererseits ist der von Dir beschriebenen Maxime auch nicht vollständig
> entsprochen worden, denn spätestens der dritte Interrupt geht ja - in
> der beschriebenen Implementierung - fallweise doch verloren.

Bei einem externen Peripheribaustein bleibt die Interruptleitung solange 
aktiv, bis alle Ereignisse abgearbeitet sind. Es geht also nichts 
verloren.
Es kann aber passieren, daß keine neue Flanke erzeugt wird, da schon 
beim Eintritt in den Handler mehrere Ereignisse vorliegen. In dem Fall 
sollte man vor Verlassen des Handlers prüfen, ob die Leitung noch aktiv 
ist oder den zustandsgetriggerten Interrupt verwenden.

Es gab allerdings auch MCs, die Interrupts ohne eigenes Pending-Flag 
hatten, z.B. der Scenix SX18. Da konnte dann nicht festgestellt werden, 
ob bei einem externen Interrupt auch gleichzeitig ein Timerinterrupt 
vorlag. Es konnten also Timerinterrupts verloren gehen.
Ich hab dann beim Lesen des Datenblattes nur mit dem Kopf geschüttelt 
und die Eval-Samples samt Datenblatt in den Papierkorb befördert.

von Fred R. (fredylich)


Lesenswert?

Hallo,

nun auch noch mein Dank an Peter Dannegger und Staubfänger.

Diese sachlichen Kommentare sind lesenswert. Nun weiß ich ein externer 
Interrupt ist nicht nur ein „Klick“ ,wie ich es lustigerweise 
bezeichne,um die Hauptschleife zu verlassen. Habe es immer nur als Art 
Aufruf eines Unterprogramm verstanden.
Wichtiger Lerneffekt:
Um Interrupt zu nutzen, sollten die Vor- Nachteile schon bei der 
Projektentwicklung hinterfragt werden.

Mit freundlichen Grüßen

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.