Forum: Mikrocontroller und Digitale Elektronik Taster am ISR-PIN entprellen


von Oliver H. (snatch)


Lesenswert?

Guten Tag zusammen,

Ich habe einen Taster an einem Interupt-PIN und wenn ich diesen Taster 
Drücke, löse ich einen Interupt aus, und das Programm springt in die 
ISR.
Aber wie entprelle ich dies? Wenn ich den Taster ohne Interupt nutze 
geht das mit debounce. Aber wie mache ich es, wenn ich den Taster als 
Interupt nutzen möchte?

Gruß und Danke
Snatch

von Peter D. (peda)


Lesenswert?

Oliver H. schrieb:
> Aber wie mache ich es, wenn ich den Taster als
> Interupt nutzen möchte?

Garnicht.
Den Interrupt nimmt man bestenfalls, um aus dem Power-Down zu erwachen. 
Danach entprellt man auf die übliche Weise.


Peter

von Oliver H. (snatch)


Lesenswert?

Ja, aber die funktion die ich damit schalte ist ein sehr wichtige und 
diese muss IMMER egal wo und wie und was das Programm macht gehen. Daher 
habe ich den Interupt verwendet. Na dann bleibt mir nur die 
Hardwareentprellung.

von Dietrich L. (dietrichl)


Lesenswert?

Peter Dannegger schrieb:
> Garnicht.

So hart würde ich das nicht sagen.

Man kann z.B. in der ISR diesen Interrupt abschalten und einen Timer 
starten. Nach Ablauf der Zeit wird das Interrupt-Flag gelöscht und der 
Interrupt wieder eingeschaltet.

Ich habe das noch nicht gemacht, nur so eine Idee, daher ohne Garantie.

Gruß Dietrich

von Peter D. (peda)


Lesenswert?

Oliver H. schrieb:
> Na dann bleibt mir nur die
> Hardwareentprellung.

Nö.
Du nimmst einfach die bewährte Entprellroutine mit Timerinterrupt 
(4-fach Abtastung, bis zu 8 Tasten parallel).
Und die Auswertung der wichtigen Taste machst Du gleich am Ende des 
Timerinterrupts.

Du mußt aber beachten, daß Du das Main unterbrochen hast an irgendeiner 
völlig zufälligen Stelle. Die Aktionen im Interrupthandler müssen daher 
sehr überlegt erfolgen.
Daher vermeidet man gerne solchen fehlerträchtigen Programmierstil und 
teilt die Mainloop in kleine Tasks auf, damit sie schnell wieder zur 
Tastenabfrage kommt.


Peter

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Oliver H. schrieb:
> Ja, aber die funktion die ich damit schalte ist ein sehr wichtige und
> diese muss IMMER egal wo und wie und was das Programm macht gehen. Daher
> habe ich den Interupt verwendet.
Ich vermute eher, dein Programmkonzept ist falsch.
Die Hauptschleife eines Programms muß in bestimmter Zeit (z.B. 20ms) 
mindestens einmal durchlaufen werden. Dann mußt du in einer 
Interruptroutine nur ein Flag setzen, und das in der Mainloop abfragen. 
Spätestens nach 20ms wird die Routine aus der Hauptschleife 
angesprungen. Wenn deine Hauptschleife länger braucht, dann ist das 
(bzw. hast du noch irgendwo) einen Fehler im Programm.

von Oliver H. (snatch)


Lesenswert?

Naja, kann sein.
Aber ich habe z.B. ein Menü, welches in einer While Schleife läuft und 
so lange ich im Menü bin ist nichts mit Hauptschleife. Ich wüsste nun 
auch nicht, wie ich das auch die schnelle anders lösen sollte.

Des weiteren frage ich einige Senoren ab, schreibe ins EEprom und 
versende und empfange Daten über RS232 was auch in den jeweiligen Subs 
einiges ein Zeit in Anspruch nimmt. Wie soll ich es da gewährleisten, 
dass mind. alle 20 ms die do-loop-schleife angesprungen wird?

Gruß
Snatch

von Oliver H. (snatch)


Lesenswert?

Dietrich L. schrieb:
> Peter Dannegger schrieb:
>> Garnicht.
>
> So hart würde ich das nicht sagen.
>
> Man kann z.B. in der ISR diesen Interrupt abschalten und einen Timer
> starten. Nach Ablauf der Zeit wird das Interrupt-Flag gelöscht und der
> Interrupt wieder eingeschaltet.
>
> Ich habe das noch nicht gemacht, nur so eine Idee, daher ohne Garantie.
>
> Gruß Dietrich

Ich habe so etwas ähnliches mal versucht. Ich habe in der ISR ganz oben 
den Interupt deaktiviert und ganz unten wieder aktiviert. Hat aber 
leider nichts geklappt.

von J.-u. G. (juwe)


Lesenswert?

Oliver H. schrieb:
> Ich habe so etwas ähnliches mal versucht. Ich habe in der ISR ganz oben
> den Interupt deaktiviert und ganz unten wieder aktiviert. Hat aber
> leider nichts geklappt.

Das ist aber nicht etwas "ähnliches", sondern etwas völlig anderes. Der 
Interrupt soll erst nach Ablauf eines Timers wieder angeschaltet werden, 
wenn sichergestellt ist, dass sie Prellphase vorüber ist.

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

Wie wär's, wenn du einfach einen Timer startest, der regelmäßig nach 
deinen Tasten sieht und dann die entsprechenden Flags setzt? Wenn du die 
Zeit des Timers richtig wählst, hast du auch gleich schon eine 
Entprellung...


Gruß
Jonathan

von Karl H. (kbuchegg)


Lesenswert?

Oliver H. schrieb:
> Naja, kann sein.
> Aber ich habe z.B. ein Menü, welches in einer While Schleife läuft und
> so lange ich im Menü bin ist nichts mit Hauptschleife. Ich wüsste nun
> auch nicht, wie ich das auch die schnelle anders lösen sollte.


In der Menüschleife kann man die wichtigen Tasten ja auch noch 
zusätzlich auswerten. Ob du jetzt nur auf Oebn/Unten/Links/Rechts und 
Enter prüfst oder zusätzlich noch den Notaus mit in die Tastenauswertung 
reinnimmst, ist auch schon egal.

> Des weiteren frage ich einige Senoren ab, schreibe ins EEprom und
> versende und empfange Daten über RS232 was auch in den jeweiligen Subs
> einiges ein Zeit in Anspruch nimmt. Wie soll ich es da gewährleisten,
> dass mind. alle 20 ms die do-loop-schleife angesprungen wird?

Gar nicht.
Diese Dinge passieren IN der do-loop.
Das ist ja der ganze Trick an der Sache.

von Dietrich L. (dietrichl)


Lesenswert?

Jonathan Strobl schrieb:
> Wie wär's, wenn du einfach einen Timer startest, der regelmäßig nach
> deinen Tasten sieht und dann die entsprechenden Flags setzt? Wenn du die
> Zeit des Timers richtig wählst, hast du auch gleich schon eine
> Entprellung...

Das ist ja noch viel einfacher, sehr gute Idee!

Gruß Dietrich

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

So könntest du das dann lösen (BASCOM):
1
Dim Button1 As Bit
2
Dim Button1_flag As Bit
3
4
Do
5
  'Bei jedem Tastendruck toggeln
6
  If Button1 = 1 Then
7
    Toggle PORTB.1
8
    Button1 = 0
9
  End If
10
  
11
  'Solange an, wie der Taster gedrückt ist
12
  If Button1_flag = 1 Then
13
    PORTB.2 = 1 
14
  Else
15
    PORTB.2 = 0
16
  End If
17
Loop
18
19
Isr:
20
  If PINB.0 = 0 Then
21
    If Button1_flag = 0 Then Button1 = 1
22
    Button1_flag = 1
23
  Else
24
    Button1_flag = 0
25
  End If
26
Return

Button1 wird nur ein Mal jedes Drücken gesetzt. Button1_flag bleibt so 
lange gesetzt, wie der Taster gedrückt ist.


Gruß
Jonathan

von Oliver H. (snatch)


Lesenswert?

O.K.

Ich schreibe nun gerade einiges um. Danke für die Anregunden.

Gruß
Snatch

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.