Eingabetaster mit zwei unterschiedlichen Funktionen (PIC)

OP #4132913
Lesenswert?
• ▲
▼
Hallo zusammen,
bei einer kleinen Bastelei möchte ich einem Eingabetaster an meinem PIC 
an verschiedenen Stellen im Programm je eine andere Funktion zuweisen. 
Sprich, wenn ich den Taster an Stelle X drücke soll A ausgeführt werden, 
wenn ich den Taster an Stelle Y drücke, soll B ausgeführt werden.

Wie löse ich das Problem am einfachsten (C/Assembler)?
Ich habe probiert, Variablen zu setzen bzw. zu löschen an den 
entsprechenden Stellen, aber dann werden bei Tastendruck immer A und B 
ausgeführt, egal ob ich bei X oder Y drücke (also genau, was ich nicht 
will). Die Taster werden jeweils im Programm per Polling abgefragt.

Ich hoffe ihr könnt mir helfen und kommt mit meiner groben Darstellung 
halbwegs zurecht, habe versucht das ganze recht einfach zu erklären :)
Gast #4132924
Lesenswert?
• ▲
▼
Das wird so nix, es sei denn du hast im Programm genug Zeit zu 
verplempern, um zu warten. Du müsstest an der jeweiligen Stelle des 
Programms die Debounce-Rotine starten und abwarten bis sie ein gültiges 
Ergebnis liefert.
Man macht das eher so: Für die beiden verschiedenen Funktionen einen 
kurzen und einen langen Tastendruck (oder einen normalen und einen 
Doppelclick) unterscheiden und das zur Separation der beiden Funktionen 
verwenden.
Gast #4132943
Lesenswert?
• ▲
▼
Ich mach das so:
Für die Eingabegeräte gibts eine Type, z.B. sowas:
1
//Beschreibt einen Button
2
typedef struct{
3
    unsigned int pressed : 1;   //button has been pressed (may be reset externally)
4
    unsigned int released : 1;  //button has been released -""-
5
    unsigned int status : 1;    //actual status of button
6
}btn;
7

8
//Da sind die buttons alle aufgelistet
9
typedef struct{
10
    btn button1;
11
    btn button2;
12
}Buttons;

Die eigentliche Variable wird als "static" in main deklariert (oder in 
eine andere Struktur eingewurstelt), alle Funktionen die mit Tastern zu 
tun haben bekommen einen Pointer drauf, unter anderem jene, die die 
Buttons einliest.

Die Funktion, welche die Bits da einträgt, wird einmal alle 10ms oder so 
aufgerufen - die schaut nach, ob sich der Taster geänder hat und setzt 
fallweise das passende Bit. Entprellt ist das dann auch gleich, wenn der 
Taster nicht länger als 10ms prellt.

Funktionen, die Benutzereingaben verarbeiten, bekommen einen Pointer da 
drauf. Die verarbeiten dann das jeweilige Ereignis und setzen das dann 
zurück. z.B. so:
1
if(Input->button1.pressed){
2
     //mach was tolles
3
     Input->button1.pressed = 0;
4
}

Damit wird jedes Ereignis genau einmal verwurstet.
Den Pointer kann man soweit herumreichen, wie man lustig ist. Man kann 
solange mit der Reaktion auf den Button warten, bis der Controller alles 
andere wichtige abgewurstelt hat.

Damit kann man Button-gesteuerte Menüs beliebig verzweigen.

Im Anhang ist ein Beispiel.
Angehängte Dateien:
#4132948
Lesenswert?
• ▲
▼
Du scheinst, eine noch etwas falsch Vorstellung von Programmabläufen, zu 
haben.
Zeig doch mal Deine Code.

Simpel schrieb:
> Das wird so nix, es sei denn du hast im Programm genug Zeit zu
> verplempern, um zu warten. Du müsstest an der jeweiligen Stelle des
> Programms die Debounce-Rotine starten und abwarten bis sie ein gültiges
> Ergebnis liefert.

Sorry, aber das ist Quatsch. Man muss nur, in der jeweiligen Situation, 
unterscheiden ob Aktion A o. B ausgeführt werden soll.
Gast #4132954
Lesenswert?
• ▲
▼
Dieter L. schrieb:
> Sprich, wenn ich den Taster an Stelle X drücke soll A ausgeführt werden,
> wenn ich den Taster an Stelle Y drücke, soll B ausgeführt werden.
>
> Wie löse ich das Problem am einfachsten (C/Assembler)?

Das fällt in die Kategorie state machine.

Status A = DiesUndDas

Status B = WennWasAnderes


Beim Ereignis Taste gedrückt fragst du den Status ab und machst dann 
entsprechend weiter.
Gast #4132962
Lesenswert?
• ▲
▼
Das Ganze macht eh nur bei einer (partiellen) State-Machine Sinn, bei 
der der Nutzer signalisiert bekommt, wie der aktuelle Stand ist, und 
auch Zeit hat zu reagieren, oder nicht... aber wenn die Eingabe eh von 
einem signalisierten Status (mit oder ohne Timeout) abhängt, ist es auch 
wurscht an welcher Stelle im Code die dazugehörige Tasteneingabe gemacht 
wird. Der Sinn des vom TO beschriebenen Vorgangs erschliesst sich mir 
irgendwie nicht...
#4133306
Lesenswert?
• ▲
▼
Dieter L. schrieb:
> Wie löse ich das Problem am einfachsten (C/Assembler)?

Beim Programmieren gilt auch "Teile und (be)herrsche", d.h. man erstellt 
kleine übersichtliche Teilaufgaben.

Zuerst braucht man eine Entprell-Lib, die fertige Ereignisse liefert und 
vorzugsweise im Timerinterrupt läuft, damit keine Drücke verloren gehen.

Und die Ereignisse holt man sich dann in den verschiedenen Kontexten 
(State-Maschinen) ab und reagiert darauf in der eine Statemaschine so 
und in der anderen eben anders.

Um zu vermeiden, daß ein Druck aus einem vorherigen Kontext was falsches 
macht, wird bei Kontextwechsel das Ereignis gelöscht (Dummy-Abfrage).

Man kann auch in verschiedenen Kontexten verschiedene Tastenfunktionen 
benutzen (z.B. lang/kurz Druck, Repeatfunktion).
(Firma: DC3AX) #4133870
Lesenswert?
• ▲
▼
Also der für mich einfachste Ablauf war damals...

Ich habe einen Timer oder eine Hauptschleife, in einem Intervall, dass 
größer als die Prellzeit meines Tasters ist, oder es gibt eine TMIN die 
mind. erreicht sein muss, damit der Tastendruck als gegeben hin genommen 
wird.

Tastenverlauf:
     TMIN TKURZ    TLANG
____|~~~~|+++++|###########|____|~~~~|+++++|###########|

Dann habe ich eine Funktion, die zählt einen Zähler hoch, so lange der 
Taster gedrückt ist. Wird der Taster los gelassen, wird geschaut, wie 
lang der Taster gedrückt war:
- Zähler < TKURZ ist, dann wird die Funktion kurzer_druck() aufgerufen
- Zähler > TKURZ ist, dann wird die Funktion langer_druck() aufgerufen

Man kann das auch noch erweitern, in dem man noch eine TLANG hinzufügt. 
Wird diese überschritten, wird die Funktion taster_halten() aufgerufen 
und der Zähler zurück gesetzt, so dass er gleich wieder los rennt. Auf 
die Art kann man seinen MP3 Player mit nur einer Taste steuern:

Kurzer Druck: PLAY/PAUSE
Mittellanger Druck: Nächster Titel
Halten: Springe im Titel

Damit die aufgerufenen Funktionen nicht den Ablauf durcheinander 
bringen, setzen diese einfach nur Flags, die dann irgendwo geordnet 
abgearbeitet werden.

Natürlich kann man das auch in Timer-Interrupts verankern und Callback 
Functions definieren, aber ich denke, das heben wir uns für den 2. Teil 
auf :)

Gruß
Ulrich

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.