Forum: Mikrocontroller und Digitale Elektronik 8051 external interrupt: mehrfaches aufrufen verhindern?


von Maverick (Gast)


Lesenswert?

Bin neu in der 8051 programmierung.

Folgendes Problem: ich will den INT0-Interrupt zum umschalten von 
Funktionen nutzen. Aber es scheint, dass bei einem Tastendruck der 
interrupt 2 oder mehr mal aufgerufen wird.

Ich nehme an, dass es mit dem typischen verhalten des Tasters 
zusammenhängt. Die klassische Lösung mit der verzögerung bringt nichts: 
auch wenn ich innerhalb des Handlers  EA = 0; setze, 20ms aktiv-warten 
und erst dann wieder EA aktiviere, scheint es doppelt aufgerufen zu 
werden.

Ich benutze den uC51-compiller.


Was wäre die beste standartlösung?

Danke

von Thomas B. (detritus)


Lesenswert?

Taster nicht per Interrupt abfragen, sondern pollen. Dann kann man auch 
gleich entprellen. Wirklich kein neues Thema hier, einfach mal suchen.

Wegen dem Mehrfach-Aufruf trotz Wartezeit:
Mit EA sperrst du nur den Aufruf des Interrupthandlers. Wenn bei EA=0 
das Interrupt-Ereignis auftritt, wird das zugehörige Interruptbit 
gesetzt, aber nix weiter unternommen. Sobald EA dann wieder da ist, 
werden die Handler aufgerufen.

von Ralf (Gast)


Lesenswert?

Hallo,

du solltest niemals in Interrupts solche Sachen wie Warteschleifen 
o.ä. einbauen. Interrupts müssen eigentlich so schnell wie möglich 
fertig sein, ausserdem blockst du damit unnötig andere Interrupts. Bei 
kleinen Projekten mag dies nicht ins Gewicht fallen, aber wenns mal 
komplexer wird, wunderst du dich dann, warum die Interrupts so langsam 
abgearbeitet werden oder womöglich Interrupts verloren gehen.

Du kannst wie bereits von  Thomas B. erwähnt per Polling arbeiten, das 
heisst, an bestimmten Stellen im Hauptprogramm prüfen, ob der Eingang 
aktiv ist. Wenn ja, dann wartest du 20ms, und prüfst nochmal. Wenn der 
Eingang dann immer noch aktiv ist, änderst du die Funktion. Das lässt 
sich in ein Unterprogramm packen, welches du dann immer per CALL-Befehl 
aufrufst.

Eine Alternative mit Interrupts gibts natürlich auch, allerdings ist der 
INT0/1-Interrupt (=Externer Interrupt) dafür ungeeignet. Nimm besser 
einen der Timer-Interrupts. Du stellst den Timer-Interrupt auf 20ms ein. 
Wenn der Interrupt zuschlägt, prüfst du den Eingang, setzt/löschst 
entsprechend ein Bit und verlässt den Interrupt. Beim nächsten 
Timer-Interrupt prüfst du das Bit. Ist es gesetzt und der Eingang immer 
noch aktiv, dann signalisierst du über ein weiteres Bit dem 
Hauptprogramm, dass sich die Funktion geändert hat. Ist der Eingang 
nicht mehr aktiv gewesen, dann gibts auch keine Nachricht ans 
Hauptprogramm, und das "Merk"-Bit innerhalb des Interrupts wird gelöscht 
(Wird natürlich auch gelöscht, wenn das Hauptprogramm die Nachricht 
erhalten hat, denn dann hat es seinen Zweck erfüllt). Das Entprellen ist 
damit auch gelöst.

Es gibt natürlich weitere Ansätze, die eben anders arbeiten. Ich 
verwende eben immer den Timer-Interrupt, wobei dieser eine kleinere 
Zeitbasis hat. Bei mir sind es etwa 138 µs. Über eine Vorteiler-Variable 
teile ich die Interrupt-Zeit in drei Abschnitte von jeweils 3,33ms. 
Jeder Abschnitt hat eine andere Aufgabe: Matrix-Tastatur-Abfrage, 
Software-Timer (10ms Auflösung) und Aktualisierung der Software-RTC. Da 
bei jedem Interrupt ein anderer Abschnitt drankommt, sind diese 3,33ms 
zueinander versetzt. Jeder Abschnitt kommt alle 10ms dran (3x3,33ms).

Du siehst, jeder hat da so seine Lösungsart :)

Wenn du Fragen dazu hast, ruhig zu.

Ralf

von Peter D. (peda)


Lesenswert?

Maverick wrote:
> Die klassische Lösung mit der verzögerung bringt nichts:

Das stimmt, man sollte daher von der klassisch schlechten Lösung 
sprechen.


Die zuverlässige Lösung entprellt und flankenerkennt immer mindestens 
einen ganzen Port parallel (aufm 8-Bitter: 8 Tasten).

Sie ist allerdings so gut, daß sie selbst für nur eine Taste die 
klassisch schlechte Lösung weit in den Schatten stellt.

Sie benutzt den Timerinterrupt und tastet 4-mal ab:

http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

Für den 8051 muß man nur die Interruptsyntax, Timerinitialisierung und 
Portdefinitionen etwas anpassen.


Peter

von Matthias (Gast)


Lesenswert?

Wenn du ein mehrfaches aufrufen des interupts verhindern möchtest,

musst du dann über software den interrupt sperren und dann später wieder 
freischalten.

ich weiß nicht mehr genau den befehl, war nur ein tipp

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.