Forum: Mikrocontroller und Digitale Elektronik Ablösende Tasten


von Felix H. (felixh)


Lesenswert?

Hallo,

Ich versuche gerade eine Steuerung in C zu schreiben und da sollen sich 
Tasten ablösen.
Das bekomme ich auch hin, jedoch schaffe ich es irgendwie nicht, dass, 
wenn man eine Taste drückt, die schon aktiv ist, diese ausgeht.

1
arrayindex=0+layer;
2
multiplexer(0x0C);
3
                                
4
I2C8574A(0x7A, out[arrayindex]);
5
multiplexer(0x08);
6
zs[arrayindex]=read(0x4B);
7
if(zs[arrayindex]==0xFE||zs[arrayindex]==0xFD||
8
   zs[arrayindex]==0xFB||zs[arrayindex]==0xF7||
9
   zs[arrayindex]==0xEF||zs[arrayindex]==0xDF||
10
   zs[arrayindex]==0xBF||zs[arrayindex]==0x7F)
11
  {
12
out[arrayindex]=zs[arrayindex];                                              
13
I2C8574A(0x7A, out[arrayindex]);                    
14
  }

Ich hab es mit allem möglichem versucht kam aber auf keinen grünen 
zweig.

Danke im Vorraus
Felix

: Verschoben durch User
von Karl H. (kbuchegg)


Lesenswert?

Und wenn du uns jetzt noch verrätst, was die 'sprechenden' Namen zs, 
arrayindex, bzw. die ganzen Hex-Konstanen da für eine Bedeutung haben, 
dann kann man dir vielleicht auch helfen.

Das eine 'ablösende Taste' ein Radio-Button ist, hat mir meine 
Kristallkugel verraten. Zuerst dachte ich, du verlierst die Tastenkappen 
auf deiner Tastatur :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was hat das mit PC-Programmierung zu tun?

Karl Heinz: Deine Kristallkugel ist heute aber besonders gut drauf!

von Felix H. (felixh)


Lesenswert?

Sorry ich dachte die Kristallkugel verrät dir alles :P

Ok da hab ich wohl schneller gehandelt als nachgedacht.
1
arrayindex=0+layer; //sagt aus, weche Stelle des Arrays angesprochen wird
2
multiplexer(0x0C); //Das ist eine Funktion, die über I²C einen Kanal in einem I²C Multiplexer freischaltet
3
                                
4
I2C8574A(0x7A, out[arrayindex]); //Der wert von out[arrayindex] wird in einen I/O Expander geschrieben (LEDs leuchten)
5
multiplexer(0x08); //Anderer Kanal in Multiplexer
6
zs[arrayindex]=read(0x4B); //Der Wert der Tasten wird ausgelesen und in den "Z"wischen"s"peicher geschrieben, da es unterschiedlichen Tastenkobinationen gibt
7
if(zs[arrayindex]==0xFE||zs[arrayindex]==0xFD||
8
   zs[arrayindex]==0xFB||zs[arrayindex]==0xF7||
9
   zs[arrayindex]==0xEF||zs[arrayindex]==0xDF||
10
   zs[arrayindex]==0xBF||zs[arrayindex]==0x7F) //Das stellt mit sicher, dass die Funktion nur ausgelöst wird wenn auch wirklich nur einen Taste gedrückt wird. Eine Tastenverriegelung
11
  {
12
out[arrayindex]=zs[arrayindex];//Der Zwischenspeicher wird in den richtigen Speicher geschrieben(Irgendwie umständlich merke ich)                                              
13
I2C8574A(0x7A, out[arrayindex]);//Der neue ausgangswert wird über I²C in den I/O Baustein geschrieben, die entsprechende LED leuchtet                    
14
  }

So das ganze ist ein Programmteil einer uC gesteuerten 16x16 
Audiokreuzschiene.

von Felix H. (felixh)


Lesenswert?

Rufus t. Firefly schrieb:
> Was hat das mit PC-Programmierung zu tun?
>
> Karl Heinz: Deine Kristallkugel ist heute aber besonders gut drauf!

Es geht mir nicht um das was mein Programm bewirkt sondern darum wie ich 
es schaffe, dass

aus 10 und 10 nicht 10 sonder 00 wird und gleichzeitig aus 10 und 01 
nicht 11 sondern 01

von Karl H. (kbuchegg)


Lesenswert?

Felix H. schrieb:

> Es geht mir nicht um das was mein Programm bewirkt sondern darum wie ich
> es schaffe, dass
>
> aus 10 und 10 nicht 10 sonder 00 wird und gleichzeitig aus 10 und 01
> nicht 11 sondern 01

Um es kurz zu machen:
Hä?

(Sollen das irgendwelche Bits sein?

Das ist doch simpel:
  Du kriegst einen Wert herein, der dir sagt welches Bit durch den
  Tastendruck betroffen ist.
  Weiters hast du eine Variable, die dir sagt, welche Taste momentan
  gerade gedrückt ist (eine 1 bedeutet: gedrückt; 0: nicht gedrückt)

  Mit dem Tasten-Wert (1-Bit auf 1 für die gedrückte Taste) schaust
  du in der Variablen nach: Ist dort an der Position eine 1, dann
  setzt du die Variable komplett auf 0 - keine Taste gedrückt
  Ist dort aber eine 0, dann wird die Variable ganz einfach auf den
  Bitcodierten Wert der gedrückten Taste gesetzt (und damit eine
  möglicherweise früher gedrückte Taste gelöscht)

Also:
schaffst du es eine Variable, nenn sie TastenNr und nicht wieder irgend 
so einen nichtssagenden Namen, so zu bestücken, dass die Zahl da drinnen 
der Nummer einer gedrückten Taste entspricht?

Den Teil musst du selber hinkriegen, dass kann nicht mal meine 
Kristallkugel aus dem Codefetzen rauslesen (und meine Kugel ist gut in 
solchen Sachen!)

Dann
1
static unsigned char TasteGedrueckt;  // '1' Bit - taste gedrückt
2
                                      // '0' Bit - Taste nicht gedrückt
3
                                      // 8 Bits - 8 Tasten die sich gegenseitig auslösen
4
5
....
6
7
8
     TastenNr = ......    du bist drann
9
10
     if( TasteGedrueckt & ( 1 << TastenNr ) )    // war sie schon gedrückt?
11
       TasteGedrueckt = 0;
12
     else
13
       TasteGedrueckt = ( 1 << TastenNr );

und das wars dann schon.

von Felix H. (felixh)


Lesenswert?

> Um es kurz zu machen:
> Hä?

ok ich versuche es nochmal irgendwie mit meinen wilden worten zu 
erklären


die tasten stelle ich durch [1](gedrückt) und [0](nicht gedrückt) dar.
es gibt 8 tasten.

und jetzt das beispiel
wenn ich den alten wert einfach dem neuen setzt wie im beispiel sieht es 
so aus
taster 1 ist aktiv, taste 4 wird gedrückt
vorher: [1][0][0][0][0][0][0][0]
eingabe:[0][0][0][1][0][0][0][0]
dann:   [0][0][0][1][0][0][0][0] //so soll es sein

taster 1 ist aktiv, taste 1 wird gedrückt
vorher: [1][0][0][0][0][0][0][0]
eingabe:[1][0][0][0][0][0][0][0]
dann:   [1][0][0][0][0][0][0][0] //so soll es nicht sein

wenn ich den alten wert aber durch xor mit dem neuen verbinde kommt das 
raus

taster 1 ist aktiv, taste 4 wird gedrückt
vorher: [1][0][0][0][0][0][0][0]
eingabe:[0][0][0][1][0][0][0][0]
dann:   [1][0][0][1][0][0][0][0]// so soll es nicht sein

taster 1 ist aktiv, taste 4 wird gedrückt
vorher: [1][0][0][0][0][0][0][0]
eingabe:[1][0][0][0][0][0][0][0]
dann:   [0][0][0][0][0][0][0][0]// so soll es sein

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Felix H. schrieb:

> taster 1 ist aktiv, taste 4 wird gedrückt
> vorher: [1][0][0][0][0][0][0][0]
> eingabe:[1][0][0][0][0][0][0][0]
> dann:   [0][0][0][0][0][0][0][0]// so soll es sein

Das heisst in einfache Worte gefasst:

1. Eine gedrückte Taste deaktiviert alle anderen
2. Wird die bereits gedrückte Taste ein zweites Mal gedrückt, 
deaktiviert sie sich auch selbst.

uint8_t tasten_checken (uint8_t port_value)
{
    static uint8_t state;

    if (state & port_value)
    {
       state = 0;
    }
    else
    {
       state = port_value;
    }
    return state;
}

Du übergibst an tasten_checken() einfach die acht bit von Deinen 8 
Tastern, du bekommst dann den neuen Taster-Status von der Funktion 
zurück.

Ist es das, was Du möchtest?

Gruß,

Frank

von Peter D. (peda)


Lesenswert?

Ich würd ja ne zentrale Entprell- und Flankenerkennungsroutine im 
Timerinterrupt machen.
Und dann kannst Du die Drückereignisse ganz leicht auswerten, wie Du 
lustig bist.

Dazu gibt es schon langjährig bewährte Lösungen in der Codesammlung.
Tastenprobleme sind für mich ein Fremdwort.


Peter

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Ich würd ja ne zentrale Entprell- und Flankenerkennungsroutine im
> Timerinterrupt machen.

Warum sollte ich Tasten, die wie Radio-Buttons wirken sollen, 
entprellen?

Gruß,

Frank

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Weil bei Dir ein weiterer Tastendruck auf dieselbe Taste diese wieder 
ausschalten soll.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rufus t. Firefly schrieb:
> Weil bei Dir ein weiterer Tastendruck auf dieselbe Taste diese wieder
> ausschalten soll.

Stimmt, an Regel 2 habe ich gar nicht mehr gedacht, nur an das 
klassische Röhrenradio :-)

Gruß,

Frank

von Felix H. (felixh)


Lesenswert?

Hallo,
Danke für die vielen Tips.
Habs jetzt hinbekommen und zusätzlich das Programm um 1kb verkleinert.
hab es so gemacht wie Frank beschrieben hat.
1
 
2
multiplexer(0x0C); //multiplexer...
3
bufferout=read(0x4B); //Tastenstatus wird in bufferout geschrieben
4
5
if(bufferout==0xFE||bufferout==0xFD||bufferout==0xFB||bufferout==0xF7||bufferout==0xEF||bufferout==0xDF||bufferout==0xBF||bufferout==0x7F)//Tastenverriegelung
6
{
7
out[arrayindex]=(out[arrayindex]==bufferout)?0xFF:bufferout;//if schleife zur überprüfung ob der neue wert dem alten entspricht                                                                                   
8
I2C8574A(0x7A, out[arrayindex]);//neue werte in die I/Os schreiben
9
}

btw. die namen der variablen haben schon sinn, da sie nur zur 
überprüfung auf die LED geschaltet werden und später auf die ausgänge 
der Kreuzschiene

von Karl H. (kbuchegg)


Lesenswert?

Felix H. schrieb:

> btw. die namen der variablen haben schon sinn,

ein Name 'arrayindex' macht niemals Sinn.

Und BTW: 'if' ist keine Schleife, sondern eine Abfrage oder 
Falluntescheidung. In einer Schleife wird etwas wiederholt abgearbeitet.

von Felix H. (felixh)


Lesenswert?

Naja ich muss mich nicht darüber streiten was bei mir Sinn und bei dir 
keinen macht.

Das if keine Schleife ist sehe ich ein.

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.