mikrocontroller.net

Forum: Projekte & Code Tasten-Matrix entprellen


Autor: Peter Dannegger (peda)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier jetzt eine Entprellroutine, wie ich sie schon in vielen Geräten 
eingesetzt habe.

Diesmal ist das Programm in C geschrieben.

Sie funktioniert im Prinzip genau so, wie die 8-Tasten-Routine. D.h. das 
Entprellen erfolgt durch Vergleich zweier aufeinanderfolgender 
Tastenzustände.

Auch das gleichzeitige Drücken mehrerer Tasten wird unterstützt, um z.B. 
Shift-Tasten zu realisieren.
Bei mehr als 2 gedrückten Tasten, müssen jedoch die Tasten durch Dioden 
entkoppelt werden, da sonst in der Matrix keine eindeutige Erkenung mehr 
möglich ist.

Um auch das gleichzeitige Betätigen mehrerer Tasten zu erkennen, kann 
diese Routine mehrmals aufgerufen werden, wenn ein Tastencode ungleich 0 
zurückgeliefert wurde. Es werden unterschiedliche Kodes beim Drücken 
bzw. Loslassen erzeugt. Somit ist eine Auswertung von Shift-Tasten oder 
Repeatfunktion möglich.


Peter

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag Herr Dannegger

das ist mir jetzt zwar peinlich aber ich muss es fragen.
die Zeile
if( column != valid_keys[i] && key_nr == 0 )
verstehe ich nicht. Mein Dozent meinte immer nur bei solchen konstrukten 
soll man klammern setzten damit man weiß was höhere priorität hat wenn 
man keine ahnung davon hat.
ich habe jetzt keine ahnung und klammern setzten nützt mir nichts um es 
zu verstehen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Array valid_keys[] hat jede Taste ein Bit.

Ändert sich nun eine Taste, ist valid_keys[] ungleich dem eingelesenen 
Byte und es muß behandelt werden.

Wurde noch keine Änderung bearbeitet, ist key_nr = 0 und diese Änderung 
kann bearbeitet werden.

Anders gesagt, falls 2 Tasten sich exakt gleichzeitig ändern (sehr 
selten, aber nicht unmöglich), wird nur die erste bearbeitet (die andere 
dann im nächsten Durchlauf).


Peter

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso

dann werden erst die beiden vergleichsoperatoren ==,|= ausgeführt und 
dann der logische && operator.

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

ich habe die routine mal AVR umgeschrieben. bis auf kleine änderungen in 
der syntax für avr-gcc musste ich noch etwas an der ansteuerung ändern, 
ein 4MHz AVR ist wohl etwas schneller wie ein 8051.

das setzen der reihen habe ich zum ende der schleife geschoben.
  for( i = 0; i < 3;  ++i )
  {
    //code.....
    //die ganzen if-abfragen

    last_keys[i] = column;    // for next debouncing
    PORTE |= 0xE0;
    PORTE &= ROW[i];    // set rows
  }
so hat bleibt ist mehr zeit, dass PINC die zustände annehmen kann. Es 
ändert sich natürlich auch der Tasten-Code, weil ja jetzt die letzte 
zeile zuerst eingelesen wird.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas W. wrote:

> ich habe die routine mal AVR umgeschrieben. bis auf kleine änderungen in
> der syntax für avr-gcc musste ich noch etwas an der ansteuerung ändern,
> ein 4MHz AVR ist wohl etwas schneller wie ein 8051.

Ne, das ist geschwindigkeitsunabhängig.

Der AVR latcht den Eingang schon im vorherigen Befehl, setzt die 
Ausgänge aber erst im nächsten.

Man muß mindestens ein NOP einfügen, damits klappt.


Peter

Autor: Andreas W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hatte es mit einen asm volatile ("nop") probiert, was auch nicht 
funktioniert hat. deshalb dann der "umweg" mit den erneuten setzen 
unten.
ich glaube so wird das programm auch nicht größer.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

Wie genau ist den die Matrix an den µC angeschlossen?

Autor: S. H. (fat32)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin wrote:
> Hallo Peter,
>
> Wie genau ist den die Matrix an den µC angeschlossen?

die frage stelle ich mir auch gerade

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin wrote:
> Hallo Peter,
>
> Wie genau ist den die Matrix an den µC angeschlossen?

Als 3*8 Matrix: die 8 Spalten an P2 und die 3 Zeilen an P0.0, P0.1, 
P0.2.


Peter

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und Pulups, oder Dioden werden nicht verwendet?

Autor: Schneekönig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

erstmal vielen Dank für die Routine.
Ich habe sie auf einem Mega8 laufen - 1A!

Man kann die Routine entweder nach Andreas W. (s.o.) anpassen oder mind. 
2 NOPs zwischen setzen und lesen der IO Register einfügen. Ich habe mich 
für die erste Möglichkeit entschieden. Wenn man die dadurch entstandene 
Verschiebung nicht mag einfach ROW[] anpassen.

Allerdings ist mir im org. Coding ein Fehler aufgefallen.
Beim setzen des Ausgangs heisst es:
P0 |= ~0x07;
P0 &= ROW[i];  

Müsste es nicht aber
P0 |= 0x07;
P0 &= ROW[i];  
sein, also ohne ~ in der ersten Zeile? Ich möchte ja die 3 Outputs auf 
High setzen, um danach genau einen Low zu setzen. Die obige Variante 
würde die anderen Pins auf dem Port high setzen und die 3 relevanten in 
Ruhe lassen...


Schneekönig

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schneekönig schrieb:
> Müsste es nicht aber
>
> P0 |= 0x07;
> P0 &= ROW[i];
> 
> sein

Ja.

Beim AVR darf man auch nicht den Port setzen, sondern das DDR-Register 
(Portbit immer low), sonst kommt es zum Kurzschluß, wenn man 2 Tasten 
drückt.
Man muß also einen Open-Drain-Ausgang nachbilden.


Peter

Autor: Rico H. (Firma: FHNW) (2she)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Martin wrote:
>> Hallo Peter,
>>
>> Wie genau ist den die Matrix an den µC angeschlossen?
>
> Als 3*8 Matrix: die 8 Spalten an P2 und die 3 Zeilen an P0.0, P0.1,
> P0.2.
>
>
> Peter

Hallo Peter,

wie sieht es aus wenn ich meine 4*4 Matrix an verschiedenen Ports habe 
(Kolonnen E4:7 und Reihen G0,G3,D4,D7)

hab ich das mit deiner Routine schnell angepasst?

Autor: Uwe S. (de0508)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe die 4x3 Matrix so verschaltet.
' --------------------------------------
'        Col0 Col1 Col2
'        |    |    |
'  D6 ---x----x----x--Row0 (1, 2, 3)
'  D5 ---x----x----x--Row1 (4, 5, 6)
'  D4 ---x----x----x--Row2 (7, 8, 9)
'  D3 ---x----x----x--Row3 (*, 0, #)
'        |    |    |
'        |    |    |
'  D2 ---+    |    |
'  D1 --------+    |
'  D0 -------------+
'
'  Legende.
'  x     : Taster
'  -,+,| : Leitung
' --------------------------------------

Anbei noch ein lauffähiges Codestück, dass in einem DTMF Generator mit 
Keypad verwendet wird.

Autor: Uwe S. (de0508)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo µC Form,

zur Vollständigkeit folgt noch der Link zu Beitrag "DTMF Encoder - 
seriell 19.200 Baud", wo die obige Klasse eingesetzt wird.

http://forum.myluna.de/viewtopic.php?f=8&t=161

_

Autor: LinWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rico H. schrieb:
> Hallo Peter,
>
> wie sieht es aus wenn ich meine 4*4 Matrix an verschiedenen Ports habe
> (Kolonnen E4:7 und Reihen G0,G3,D4,D7)
>
> hab ich das mit deiner Routine schnell angepasst?

Ohne Peter da zu nahe treten zu wollen. Ich würde das selbst nochmal 
ganz neu schreiben. Diesen veröffentlichten Code halte ich nicht 
unbedingt für nachahmenswert

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LinWin schrieb:
> Diesen veröffentlichten Code halte ich nicht
> unbedingt für nachahmenswert

Hast Du Dir überhaupt mal die Beschreibung durchgelesen?
Vermutlich nicht.
Diese Routine kann nämlich erheblich mehr als die üblichen Routinen.

Wenn Du erkennen kannst, daß sie Mist ist, dann mußt Du ja auch wissen, 
wie man es "richtig" macht.
Zeig dochmal, wie Du diese Funktionalität (press-, release-code, 
multiple keypress) realisieren würdest.

Autor: Gerhard O. (gerhard_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

Deine "Magic" funktioniert bei meinen Projekten 100%. Vielen Dank für 
solchen wunderbaren Code! Sogar bei Portierungen macht er praktisch 
keinerlei Schwierigkeiten. Er lässt zumindest bei mir keine Wünsche 
offen und man kann sehr viel damit machen. Meine Letzte Adaptierung 
funktioniert jetzt übrigens einwandfrei auf der WSB über eine SPI 
MCP23S18 Schnittstelle. Bis jetzt portierte ich es auf STM32, einige 
PICs, AVR(Codevision), und ZILOG encore.

Deine Quadratur Encoder Lösung ist auch eine sehr feine Sache.


mfg,
Gerhard

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Beim AVR darf man auch nicht den Port setzen, sondern das DDR-Register
> (Portbit immer low), sonst kommt es zum Kurzschluß, wenn man 2 Tasten
> drückt.
> Man muß also einen Open-Drain-Ausgang nachbilden.

Es wird also immer nur eine Reihe als Input geschaltet (über DDRx) und 
dann alle Spalten angeguckt... aber mit Portbit (PORTx) immer low fehlt 
mir doch der interne Pullup bei active low Tasten? ODer brauche ich die 
Pullups nur an den Spalten?

So ganz bin ich auch noch nicht dahinter gekommen, wie mehrere 
gleichzeitig gedrückte Tasten unterschieden werden. Ab wann braucht man 
da Dioden und wo kommen die hin?

Kann vielleicht jemand eine funktionierende Portierung für AVR hier 
einstellen?

Danke.

Autor: Gerhard O. (gerhard_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Werner,


Werner schrieb:
> Peter Dannegger schrieb:
>> Beim AVR darf man auch nicht den Port setzen, sondern das DDR-Register
>> (Portbit immer low), sonst kommt es zum Kurzschluß, wenn man 2 Tasten
>> drückt.
>> Man muß also einen Open-Drain-Ausgang nachbilden.

Man kann bei die meisten MCUs OPEN-DRAIN Ausgänge simulieren indem man 
alle Keypad Ausgangs PORT BITS einmalig auf Null setzt und die Ausgänge 
sequenziell nur mit dem DDRn Register als jeweilig eingeschalteten 
Ausgang ansteuert. Die jeweilig unbenutzten Ausgänge verhalten sich dann 
immer als Eingänge. In anderen Worten, nur der jeweilig angesteuerte 
PORT-PIN liegt auf Masse um die Spalten runter zu ziehen und ein 
Kurzschluss zwischen irgendwelchen Spaltenausgängen haben keine Wirkung.

>
> Es wird also immer nur eine Reihe als Input geschaltet (über DDRx) und
> dann alle Spalten angeguckt... aber mit Portbit (PORTx) immer low fehlt
> mir doch der interne Pullup bei active-low Tasten? ODer brauche ich die
> Pullups nur an den Spalten?

Die Pullups braucht man nur bei den Eingängen. Viele MCUs haben interne 
Pullup Widerstände die man einschalten kann. Beim AVR geht das ganz 
einfach indem man die PORTn Register auf H setzt und die PINs mit dem 
DDRn Register in den Eingang Modus versetzt. Das schaltet automatisch 
die Pullups ein. Bei anderen MCUs wie PIC geht das bei vielen älteren 
Modellen nur am PORTB. Ansonsten musst Du eben extra 2-10KOHM 
Widerstände einbauen.

Diskrete Widerstände im Bereich von 2-10K haben aber auch den Vorteil 
dass mehr Strom durch die Tastenschalter fließt und sie dann 
zuverlässiger arbeiten. Viele Kontaktmaterialien brauchen einen gewissen 
Mindeststrom um zuverlässig funktionieren zu können.

>
> So ganz bin ich auch noch nicht dahinter gekommen, wie mehrere
> gleichzeitig gedrückte Tasten unterschieden werden. Ab wann braucht man
> da Dioden und wo kommen die hin?

Da jedes Spalte einzeln zeitlich sequenziell angesteuert wird lässt sich 
das im Code wieder elegant entflechten. Ein Kurzschluss zwischen 
gleichen Spalten macht sowieso nichts aus und ein Kurzschluss über ein 
oder mehrere Spalten macht auch nichts aus weil sich das in den 
eingelesenen Werten ersichtlich ist. Da der ganze Scan Vorgang zeitlich 
sequenziell abläuft lässt sich alles richtig ableiten.
>
> Kann vielleicht jemand eine funktionierende Portierung für AVR hier
> einstellen?

Habe im Augenblick keine Portierung für AVR (Nur PIC). Das Beispiel von 
Peter ist aber für den AVR gezeigt und sollte anstandslos funktionieren.

Es ist übrigens interessant zu sehen wie sein Code funktioniert. Wenn Du 
auf eine oder mehrere Tasten drückst wird jede Taste richtig 
nacheinander angezeigt. So, wenn man mehr als eine Taste drückt wird 
nacheinander im Zug der Portsequenz der Keycode ausgegeben:

z.B. Taste 1 (2+3+4) gleichzeitig:

[0x81] [0x82] [0x83] [0x84]...
beim loslassen einer jeweiligen Taste wird das MSB bit geloescht:

Drücken: [0x81] loslassen: [0x01]

Bei mir verwende ich eine lookup table (LUT) um den Keycode um z.B mit 
einem 4x4 Tastenfeld die nummern 0-9A-F zu generieren. Mit dieser LUT 
lässt sich dann für jede Taste der gewünschte Keycode zuordnen.

Ich hoffe das hilft Dir etwas weiter,

mfg,
Gerhard






>
> Danke.

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich habe es verstanden...

Die zu überprüfende Reihe wird per Ausgang auf low gezogen (PORTx.y = 0 
und DDRx.y = 1).
Die anderen Reihen sind floatende Eingänge (PORTx.y = 0 und DDRx.y = 0).

Alle Spalten gehen zu Eingängen mit aktiviertem Pullup.
Nun kann ich anhand der Spalten die Taster in der aktiven Reihe 
auswerten.
Ein gedrückter Taster in der zu überprüfenden Reihe zieht den 
Spalteneingang auf low.
Ein gedrückter Taster in einer anderen Reihe kann über den floatenden 
Eingang der Reihe die Spalte nicht auf low ziehen und stört nicht.

Die Reihen werden nun nacheinander ausgewertet -> multiplexing.

Ist das so richtig?

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wofür bräuchte man denn dann noch Dioden, wenn man mehrere Tastendrücke 
gleichzeitig auswerten möchte?

Autor: Gerhard O. (gerhard_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner schrieb:
> Ich glaube ich habe es verstanden...
>
> Die zu überprüfende Reihe wird per Ausgang auf low gezogen (PORTx.y = 0
> und DDRx.y = 1).
> Die anderen Reihen sind floatende Eingänge (PORTx.y = 0 und DDRx.y = 0).

Wenn Du aber (PORTx.y = 1 und DDRx.y = 0) einstellst dann aktivieren 
sich die eingebauten Port Pullup Widerstände.

Wie schon gesagt favorisiere ich extra diskrete Pullup Widerstände weil 
man dann mehr Strom durch die Tasten fließen lassen kann was die 
Zuverlässigkeit der Tastenaktion erhöhen kann.

>
> Alle Spalten gehen zu Eingängen mit aktiviertem Pullup.
> Nun kann ich anhand der Spalten die Taster in der aktiven Reihe
> auswerten.
> Ein gedrückter Taster in der zu überprüfenden Reihe zieht den
> Spalteneingang auf low.

Der jeweilig vom Code aktivierte Port PIN macht das;-)

> Ein gedrückter Taster in einer anderen Reihe kann über den floatenden
> Eingang der Reihe die Spalte nicht auf low ziehen und stört nicht.

Ja. Da die übrigen ROW Output Pins als Eingange wirken macht das nichts 
aus.
>
> Die Reihen werden nun nacheinander ausgewertet -> multiplexing.
>
> Ist das so richtig?
Ja. Der Rest passiert durch Peter's Magic Code;-)

Gerhard

Autor: Gerhard O. (gerhard_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner schrieb:
> Wofür bräuchte man denn dann noch Dioden, wenn man mehrere Tastendrücke
> gleichzeitig auswerten möchte?

Wenn man es wie beschrieben macht sind die Dioden überflüssig. Die 
Dioden sind nur notwendig wenn man keinen OPEN DRAIN Ausgänge zur 
Verfügung hat.

Ich setzte mal ein Shift-Register (74HC164) als ROW Treiber ein. In 
diesem Fall waren die Dioden notwendig.

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, danke, dann hab ich es jetzt verstanden :-)

(PORTx.y = 1 und DDRx.y = 0) hab ich ja bei der Reihe auch nicht 
geschrieben.
Das braucht man dann nur bei der Spalte oder eben externe Pullups.

Und ja, um genau zu sein, der Taster verbindet nur die Reihe mit der 
Spalte.
Der Spalteneingang wird dann durch den auf low gestellten (aktiven) 
Reihenausgang auf low gezogen.

Autor: Werner (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Habe das mal für AVR angepasst.
Es kompiliert zumindest, kann es aber gerade mangels HW nicht testen.

Es fehlt aber auch noch die Anpassung mit dem NOP.
Kann mir jemand helfen, wo das genau zwischen muss?
Danke!

Autor: Uwe S. (de0508)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das hat Peter doch geschrieben:

Beitrag "Re: Tasten-Matrix entprellen"

Wie immer gibt es diese Info zum Lesen im Datenblatt deines µC im 
Abschnitt Ports.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner schrieb:
> Wofür bräuchte man denn dann noch Dioden, wenn man mehrere Tastendrücke
> gleichzeitig auswerten möchte?

Sobald mehr als 2 Tasten gleichzeitig.
Ohne Dioden kann es bei 3 Tasten gedrückt zu einer 4. Phantomtaste 
kommen.

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du das mit der Phantomtaste genauer erklären, wie das zustande 
kommt?
Das verstehe ich noch nicht.

Wegen des NOPs verstehe ich das so, dass vor dem Einlesen des Pins nach 
dem Setzen der Ausgänge ein bis zwei Takte gewartet werden muss, also 
so:
KEYPAD_ROW_DDR |= KEYPAD_ROW_MASK;      //simulation of open drain output
KEYPAD_ROW_DDR &= ROW[i];               // set rows (active row is low output, all other rows are floating input)
nop();
nop();
column = KEYPAD_COL_PIN; 

Richtig?

Autor: Kai G. (shangkai)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner schrieb:
> Kannst du das mit der Phantomtaste genauer erklären, wie das zustande
> kommt?
> Das verstehe ich noch nicht.

Schau mal hier : 
http://www-user.tu-chemnitz.de/~heha/Mikrocontroll...

Ist in Tastenmatrix.c nicht noch ein Fehler drin?

Ohne Dioden nur das DDRx Bit setzen dessen Reihe ausgewertet werden 
soll.
  //uint8_t ROW[] = { 0x01, 0x02, 0x04 };    // low active
  uint8_t ROW[] = { KEYPAD_ROW_0, KEYPAD_ROW_1, KEYPAD_ROW_2 };    // low active

  for( i = 0; i < 3;  ++i ){

    KEYPAD_ROW_DDR |= KEYPAD_ROW_MASK;      //simulation of open drain output
    KEYPAD_ROW_DDR &= ROW[i];        // set rows (active row is low output, all other rows are floating input)
    asm volatile ("nop");
    asm volatile ("nop");
    column = KEYPAD_COL_PIN;            // read column


Mit Dioden alle PORTx Bit's setzen bis auf das Bit welches augewertet 
werden soll.
  //uint8_t ROW[] = { ~0x01, ~0x02, ~0x04 };    // low active
  uint8_t ROW[] = { ~KEYPAD_ROW_0, ~KEYPAD_ROW_1, ~KEYPAD_ROW_2 };    // low active

  for( i = 0; i < 3;  ++i ){

    KEYPAD_ROW_PORT |= KEYPAD_ROW_MASK;      //simulation of open drain output
    KEYPAD_ROW_PORT &= ROW[i];        // set rows (active row is low output, all other rows are floating input)
    asm volatile ("nop");
    asm volatile ("nop");
    column = KEYPAD_COL_PIN;            // read column

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kai Großpietsch schrieb:
> Schau mal hier :
> http://www-user.tu-chemnitz.de/~heha/Mikrocontroll...
>
> Ist in Tastenmatrix.c nicht noch ein Fehler drin?
>
> Ohne Dioden nur das DDRx Bit setzen dessen Reihe ausgewertet werden
> soll.
>
 
   //uint8_t ROW[] = { 0x01, 0x02, 0x04 };    // low active 
   uint8_t ROW[] = { KEYPAD_ROW_0, KEYPAD_ROW_1, KEYPAD_ROW_2 };    // low active 
 
   for( i = 0; i < 3;  ++i ){ 
 
     KEYPAD_ROW_DDR |= KEYPAD_ROW_MASK;      //simulation of open drain output 
     KEYPAD_ROW_DDR &= ROW[i];        // set rows (active row is low output, all other rows are floating input) 
     asm volatile ("nop"); 
     asm volatile ("nop"); 
     column = KEYPAD_COL_PIN;            // read column
>

Danke, das mit dem Kurzschluss bei mehr als 2 Tasten gleichzeitig habe 
ich jetzt verstanden.

Ich bin der Meinung, dass man die simulierten Open Drain Ausgänge auch 
mit Dioden nutzen kann. Nur andersrum, gibt es Probleme, nämlich mit 
normalen Ausgängen (über PORT) und keinen Dioden...

Ich meine, dass der Code im Simulator funktioniert hätte, bin aber 
gerade verunsichert und würde es gerade so machen:
#define KEYPAD_ROW_0    (1<<PD0)
#define KEYPAD_ROW_1    (1<<PD1)
#define KEYPAD_ROW_2    (1<<PD2)
#define KEYPAD_ROW_MASK (KEYPAD_ROW_0 | KEYPAD_ROW_1 | KEYPAD_ROW_2)    //all row pins

[...]

//uint8_t ROW[] = { 0x01, 0x02, 0x04 };
uint8_t ROW[] = { KEYPAD_ROW_0, KEYPAD_ROW_1, KEYPAD_ROW_2 };

for( i = 0; i < 3;  ++i ){
  //simulation of open drain output  
  KEYPAD_ROW_DDR &= ~KEYPAD_ROW_MASK;   // set all rows to input    
  KEYPAD_ROW_DDR |= ROW[i];             // set active row to output (active row is low output, all other rows are floating inputs due to PORTx = 0 for all rows) 
  asm volatile ("nop");
  asm volatile ("nop"); 
  column = KEYPAD_COL_PIN;            // read column

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werner schrieb:
> Kannst du das mit der Phantomtaste genauer erklären, wie das zustande
> kommt?

Mal die Schaltung einer 2 * 2 Matrix auf und drücke 3 Tasten. Dann wird 
auch die 4. Taste als gedrückt erkannt, da die 3 Tasten den Stromkreis 
dafür schließen.
Hat jede Taste eine Diode in Reihe, werden nur die 3 Tasten gemeldet, 
die wirklich gedrückt sind.

Autor: Fabian B. (fabs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe die Funktion gerade mal auf meinen Cortex-M3 umgesetzt mit 
einer 2x9 Matrix.
Funktioniert auch soweit wunderbar, nur fehlt mir sowas wie eine 
"get_key_pressed" und "get_key_released" Funktion, die ich in der main 
nutzen kann.
Also etwas, dass den Tastendruck nur einmal zurückgibt.

GetKey rufe ich im Timer alle 10ms auf und speichere die Rückgabe in 
einer Variablen. Daurch evaluiert aber die Abfrage in der Main je nach 
Durchlaufzeit vielfach.

Soll ich die Variable zum Zwischenspeichern einfach nach der Evaluierung 
'0' setzen?

Wie macht ihr das?

Gruß
Fabian

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fabian B. schrieb:
> Daurch evaluiert aber die Abfrage in der Main je nach Durchlaufzeit
> vielfach.
Was könnte das bedeuten?

> nach der Evaluierung '0' setzen?
Was "evaluierst" (= "bewertest") du denn wie?

> Daurch evaluiert aber die Abfrage in der Main je nach Durchlaufzeit
> vielfach.
Du könntest mal deine "Main" hier anhängen, dann könnte man die mal 
evaluieren...

Autor: Fabian B. (fabs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Lothar,
 da gibts nicht anzuhängen ... die Main liest derzeit nur die Taste und 
gibt sie über die serielle aus.
Hier setze ich jetzt schon keyp = 0 um eine Taste nur einmal zu 
behandeln.
  while (true) {
    if((keyp > 0)){
      printf("key_nr: %i\n\r", keyp);
      keyp = 0;
    }
  }

keyp selbst ist eine globale Variable (volatile uint8_t), die im 
10ms-Timer mit
  keyp = kbd_get_key();

"gefüllt" wird.

So funktioniert das auch, aber mein Frage war ja ob das so gedacht ist 
oder ob's da was eleganteres gibt, was ich übersehe. Vergleichbar der 
get_key Funktionen aus PeDas "normaler" Tastenentprellung.

Gruß
Fabian

Autor: Fabian B. (fabs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keiner mehr?
Vielleicht kann ja ein Anwender der Funktion die Tastenauswertung aus 
seinem Programm posten...

Gruß
Fabian

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.