Wie am besten meine Taster Verriegeln ?

OP #5579812
Lesenswert?

Guten Tag,

ich möchte mit jedem Taster einen Kanal Einschalten, wenn der jeweilige 
Kanal gewählt wird soll der zuletzt gewählte Kanal ausgeschaltet werden, 
das heisst es darf kein anderer eingeschaltet werden, wie kann ich hier 
am besten vorgehen um die fünf Taster gegenseitig zu verriegeln ??


vielleicht kann mir bitte jemand weiterhelfen ??


1
/*
2
 * Tasterverriegelung.c
3
 *
4
 * Created: 07.10.2018 12:01:59
5
 * Author : USER
6
 */ 
7
# define F_CPU 8000000
8
#include <avr/io.h>
9
#include <util/delay.h>
10

11
#define Taster1_Down !(PINB&(1<<PB6))
12
#define Taster2_Down !(PINB&(1<<PB7))
13
#define Taster3_Down !(PIND&(1<<PD5))
14
#define Taster4_Down !(PIND&(1<<PD6))
15
#define Taster5_Down !(PIND&(1<<PD7))
16

17
int Flag1 = 0;
18
int Flag2 = 0;
19
int Flag3 = 0;
20
int Flag4 = 0;
21
int Flag5 = 0;
22

23
#define Kanal1_HIGH   PORTC |= (1<<PC0)
24
#define Kanal2_HIGH   PORTC |= (1<<PC1)
25
#define Kanal3_HIGH   PORTC |= (1<<PC2)
26
#define Kanal4_HIGH   PORTC |= (1<<PC3)
27
#define Kanal5_HIGH   PORTC |= (1<<PC5)
28

29
#define Kanal1_LOW    PORTC &= ~(1<<PC0)
30
#define Kanal2_LOW    PORTC &= ~(1<<PC1)
31
#define Kanal3_LOW    PORTC &= ~(1<<PC2)
32
#define Kanal4_LOW    PORTC &= ~(1<<PC3)
33
#define Kanal5_LOW    PORTC &= ~(1<<PC5)
34

35

36

37

38
int main(void)
39
{    
40
  // EINGÄNGE Setzen
41
  DDRB = (1<<PB7)|(1<<PB6);
42
  DDRD = (1<<PD5)|(1<<PD6)|(1<<PD7);
43
  // Pullup
44
  PORTB = (1<<PB7)|(1<<PB6);
45
  PORTD = (1<<PD5)|(1<<PD6)|(1<<PD7);
46
  
47
    
48
    while (1) 
49
    {
50
    }
51
}
#5579853
Lesenswert?

Erstmal ist es natürlich ganz einfache: wird eine Taste erkannt wird das 
entsprechende Bitmuster auf den Port geschrieben, was nur eine 1 hat.

Interessanter werden dann die Randbedingen. Was passiert wenn mehrere 
Tasten "gleichzeitig" gedrückt werden? Gar nichts? Die zuerst gedrückte 
gewinnt? oder die zuletzt losgelassene? Schöner ist es, wenn direkt beim 
Drücken was passiert und nicht erst beim loslassen. Also muss in der 
Zeit, in der eine Taste noch gedrückt ist, die weitere 
Abfrage/Auswertung unterbleiben. Neu geht erst wieder, wenn alle 
losgelassen wurden.
Gast #5579855
Lesenswert?

Hallo,

Wichtiger ist noch, dass man alle Taster sauber abfragt (entprellt) und 
auch die Ereignisse, Taster wurde gedrückt oder losgelassen, reagieren 
kann.

Es fehlt also noch eine Timer basierenede Tasterentprellung.

Dann würde ich ein Ausgang-Bit-Variable <bit_output> definieren, die die 
realen Ausgangszustände abbildet.
Dann kann man doch einfach die neue gedrückte Taste in der zugehörigen 
Bitposition der Variable <bit_output> setzen und der Ausgabefunktion 
übergeben.
Diese setzt oder löscht dann anhand einer "0" oder "1" an einer 
Bitposition das zugeordnete Bit am Ausgang.
OP #5579932
Lesenswert?

Karl M. schrieb:
> Hallo,
>
> Wichtiger ist noch, dass man alle Taster sauber abfragt (entprellt) und
> auch die Ereignisse, Taster wurde gedrückt oder losgelassen, reagieren
> kann.
>
> Es fehlt also noch eine Timer basierenede Tasterentprellung.

also die Entprellung soll anders stattfinden und zwar indem ich einen 
invertierenden Schmitttriger zwischen Taster und I/O schalte.

Dann würde ich ein Ausgang-Bit-Variable <bit_output> definieren, die die
realen Ausgangszustände abbildet.
Dann kann man doch einfach die neue gedrückte Taste in der zugehörigen
Bitposition der Variable <bit_output> setzen und der Ausgabefunktion
übergeben.
Diese setzt oder löscht dann anhand einer "0" oder "1" an einer
Bitposition das zugeordnete Bit am Ausgang.

das kapier ich irgendwie nicht, gibt es da irgendwo ein Beispiel oder 
ähnliches wo ich mir das mal abschauen kann ?
Gast #5579956
Lesenswert?

Michael H. schrieb:
> das heisst es darf kein anderer eingeschaltet werden

Dann ist es auch überflüssig, 5 x int für die Taster zu speichern, es 
reicht einer, der die Nummer des Tasters enthält, das macht den Zustand 
von vornherein eindeutig. Ein Tastendruck setzt den Zustand auf die 
zugehörige Nummer, und es wird das zur Nummer gehörende Bitmuster 
ausgegeben. Oder ist das zu kompliziert?

Georg
Gast #5579978
Lesenswert?

Karl M. schrieb:
> Es fehlt also noch eine Timer basierenede Tasterentprellung.

Die Entprellung in diesem Spezialfall hier entbehrlich, weil es nur 
darum geht, zu erkennen, dass ein Taster min. 1x gedrueckt wurde. Ob das 
1x oder 100x erkannt wird, aendert nichts.

wendelsberg
Gast #5580002
Lesenswert?

Karl M. schrieb:
> Wichtiger ist noch, dass man alle Taster sauber abfragt (entprellt)

Spielt bei dieser Anwendung keine Rolle.

Das Problem hier ist die Aufgabenstellung. Die entspricht nämlich NICHT 
einem Tastenaggregat.

Michael H. schrieb:
> ich möchte mit jedem Taster einen Kanal Einschalten, wenn der jeweilige
> Kanal gewählt wird soll der zuletzt gewählte Kanal ausgeschaltet werden,
> das heisst es darf kein anderer eingeschaltet werden

sondern einem dead lock, bricked: Wenn EIN Mal ein Kanal durch 
Tastendruck gewählt wurde (wer zuerst kommt mahlt zuerst) kannn NIE MEHR 
ein anderer gewählt werden, denn die sind ja nun verriegelt und kann 
nicht mehr eingeschaltet werden.

Da er aber von "der zuletzt gewählte ausgeschaltet" redet, meint er wohl 
nicht, was er hier als Blödsinn hingeschrieben hat. Er soll sich erst 
mal lklar werden, welche Logik er wirklich will, dann kann man die auch 
implementieren. Denn Unlogik macht ein Prozessor nicht mit.

Eventuell sind die anderen Kanäle nur so lange verriegelt, bis der 
zuerst gedrückte Taster wieder lisgelassen wird. Wenn dann aber mehrere 
andere Taster immer noch gedrückt gehalten wurden, wäre die Frage, 
welchen man seinen Ausgang einschalten lässt. Oder erst denjenigen, den 
man erneut niederdrückt. Viele Interpretationsmöglichkeiten der 
halbgaren Aufgabe.
Gast #5580032
Lesenswert?

Michael H. schrieb:
>> indem du nur definiert 1 Bit in PORTC setzt...
> das ist das, was ich ausprobieren möchte, nur kann ich mir gerade
> überhaupt nicht vorstellen wie das aussehen soll, kann mir  bitte hier
> jemand einen Ansatz zeigen

Gerne
1
#define Kanal1 (1<<PC0)
2
#define Kanal2 (1<<PC1)
3
#define Kanal3 (1<<PC2)
4
#define Kanal4 (1<<PC3)
5
#define Kanal5 (1<<PC5)
6
#define AlleKanaele  (Kanal1+Kanal2+Kanal3+Kanal4+Kanal5)
7

8
PORTC = (PORTC & ~AlleKanaele) | Kanal1;

(PORTC & ~AlleKanaele) setzt alle Kanäle auf Low und lässt die übrigen 
Bits unverändert.

| Kanal1 setzt den gewünschten Kanal auf High.

Beides zusammen löscht also alle Kanäle und setzt den einen gewünschten 
Kanal. Dieser Lösungsansatz setzt voraus, dass alle Kanäle im selben 
Port sind.
Gast #5580162
Lesenswert?

wendelsberg schrieb:
> Die Entprellung in diesem Spezialfall hier entbehrlich, weil es nur
> darum geht, zu erkennen, dass ein Taster min. 1x gedrueckt wurde. Ob das
> 1x oder 100x erkannt wird, aendert nichts.


Wie auch immer...

Ich kann dir ein Arduino Beispiel liefern, wie sowas aussehen könnte.
Habe ich aus einem anderen Projekt raus geschnitten, und so eben auf 
dein Problem angepasst.

Die betreffenden Pins/Ports sind anders konfiguriert, um es testen zu 
können.
Da ist also Anpassungsarbeit nötig.
Findet sich aber alles schön übersichtlich in einem Array.

Leider kann ich gerade kein C testen, darum C++ Code.
Allerdings ist der Code sehr C artig.
Sollte also umformbar sein.

Für C müssten die Daten Typen und die Schleifen umgebaut werden.
1
//# define F_CPU 8000000
2
//#include <avr/io.h>
3
//#include <util/delay.h>
4

5

6

7
using Register = volatile byte *;
8

9
struct Port
10
{
11
  Register ddr;
12
  Register pin;
13
  Register port;
14
  byte    maske; 
15
};
16

17
struct TasterDingen
18
{
19
  Port taster;
20
  Port out;
21
};
22

23
using TasterArrayType = TasterDingen[5];
24

25
TasterArrayType td {
26
                       {{&DDRB,&PINB,&PORTB,(1<<PB0)},{&DDRC,&PINC,&PORTC,(1<<PC0)}},
27
                       {{&DDRB,&PINB,&PORTB,(1<<PB1)},{&DDRC,&PINC,&PORTC,(1<<PC1)}},
28
                       {{&DDRB,&PINB,&PORTB,(1<<PB2)},{&DDRC,&PINC,&PORTC,(1<<PC2)}},
29
                       {{&DDRB,&PINB,&PORTB,(1<<PB3)},{&DDRC,&PINC,&PORTC,(1<<PC3)}},
30
                       {{&DDRB,&PINB,&PORTB,(1<<PB4)},{&DDRC,&PINC,&PORTC,(1<<PC4)}},
31
                     };
32

33

34

35
void alleAus(TasterArrayType &td)
36
{
37
  for(TasterDingen &t:td) *(t.out.port) &= ~t.out.maske;
38
}
39

40
int scan(TasterArrayType &td) // liefert den index einer gedrueckten Taste
41
{
42
  int i = 0;
43
  for(TasterDingen &t:td)
44
  {
45
    if(!(*(t.taster.pin) & t.taster.maske)) return i; 
46
    i++; 
47
  }
48
  return -1; // kein taster gedrueckt
49
}
50

51

52
int main(void)
53
{   
54
  for(TasterDingen &t:td) 
55
  {
56
    // Inputs vorbereiten
57
    *(t.taster.ddr)  |= t.taster.maske;
58
    *(t.taster.port) |= t.taster.maske;
59

60
    // Outputs vorbereiten
61
    *(t.out.ddr) |= ~t.out.maske;
62
  }
63

64
  int last = -1; // -1 ist kein taster gedrueckt
65
    
66
  while(1) 
67
  {
68
    int s = scan(td);
69
    if((s >= 0) && (s != last))
70
    {
71
     last = s;
72
     alleAus(td);
73
     *(td[s].out.port) |= td[s].out.maske; // den einen Ausgang ein
74
    }
75
  }
76
}
#5581395
Lesenswert?

Michael H. schrieb:
> ich möchte mit jedem Taster einen Kanal Einschalten, wenn der jeweilige
> Kanal gewählt wird soll der zuletzt gewählte Kanal ausgeschaltet werden,
> das heisst es darf kein anderer eingeschaltet werden, wie kann ich hier
> am besten vorgehen um die fünf Taster gegenseitig zu verriegeln ??

Hallo, ich kann zwar kein "C" oder so was...aber ich denke, wenn dein 
Programm mit Initialisieren fertig ist, dann ist jeder Kanal inaktiv und 
du wartest auf eine Eingabe. Das erste Eingabe-Low, das du pollst, setzt 
den Eingang und setzt alle anderen zurück. Wenn nun jemand schlau 
"Klavier spielt", dann gewinnt immer Einer...und alle anderen sind raus. 
Wie du nun die zeitlichen Zuordnungen zwischen den Signalen legst, ist 
allein dein Gustus. Viel kann man da nicht falsch machen! Es sei denn du 
hast Menschen, die Eingaben im Bereich des Prozessortakts tätigen 
können.
Gruß Rainer

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren