Forum: Mikrocontroller und Digitale Elektronik 3x4 Tastenmatrix auslesen


von rudi (Gast)


Angehängte Dateien:

Lesenswert?

Habe mal ein C-Programm geschrieben, mit dem ich folgendes vorhabe...

Ich habe eine Tastenblock mit 12 Tasten. (3x4 Matrix Anschluß)-->also 3
Spalten und vier Zeilen. Um das Auslesen zuz realisieren habe ich die
Spalten als Eingänge mit Pull ups und die Zeilen als Ausgänge definiert.
Ausgangspegel =high ("1"). Das heißt jetzt wenn ich eine Taste z.b die
Zahl 3 erkennen möchte (Zeile 1 und Spalte 3) , schreibe ich am ausgang
Zeile 1 eine "0" und überprüfe ob eine "0" in Spalte 3 eingelesen wird.

--> Ich möchte einen 4stelligen Code eingeben...

Bitte schaut euch den Code mal an. Er ist bestimmt noch 
optimierungswürdig...

Vielen Dank für eure Hilfe

@ Hannes Lux (hannes)

Vielen Dank für deine Mühe, jedoch habe ich keinerlei Erfahrung mit dem 
Assembler und möchte das jetzt gerne in C realisieren. Habe mal ein 
neues Thema geöffnet, da das alte zu undurchsichtig war.
THX

rudi

von Sonic (Gast)


Lesenswert?

So habe ich das gelöst:
1
if (PINA != 15)        // nur bei gedrückter Taste abfragen
2
  {  
3
    PORTA = 0b00001111;  // Spalten abfragen
4
    _delay_us(1);
5
    Ergebnis = PINA;
6
    
7
    DDRA = 0b00001111;            
8
    PORTA = 0b11110000;
9
    
10
    PORTA = 0b11110000;  // Zeilen abfragen
11
    _delay_us(1);
12
    Ergebnis += PINA;  // Zeilen und Spalten verknüpfen
13
    
14
    DDRA = 0b11110000;
15
    PORTA = 0b00001111;  // Port-Ausgangszustand wiederherstellen
16
    
17
    switch (Ergebnis)
18
      {
19
      case 119: T_Byte = '0'; break;  // Bitmuster auswerten und Byte zuweisen
20
      case 123: T_Byte = '.'; break;
21
      case 125: T_Byte = '-'; break;
22
      case 126: T_Byte = 'E'; break;
23
      case 183: T_Byte = '1'; break;
24
      case 187: T_Byte = '2'; break;
25
      case 189: T_Byte = '3'; break;
26
      case 190: T_Byte = 'C'; break;
27
      case 215: T_Byte = '4'; break;
28
      case 219: T_Byte = '5'; break;
29
      case 221: T_Byte = '6'; break;
30
      case 222: T_Byte = 'D'; break;
31
      case 231: T_Byte = '7'; break;
32
      case 235: T_Byte = '8'; break;
33
      case 237: T_Byte = '9'; break;
34
      case 238: T_Byte = 'F'; break;
35
      default : T_Byte = ' '; break;
36
      }
37
    
38
    for(unsigned char i=0;i<15;i++) // Pause 15 x 10ms = 150ms (entprellung)
39
      {
40
        _delay_ms(255);  // 255ms/16MHz=16ms
41
      }
42
  }

Vielleicht kannste was mit anfangen?

von Falk (Gast)


Lesenswert?

@Sonic

>    _delay_ms(255);  // 255ms/16MHz=16ms

Was soll das? _delay_ms() macht schon die richtige Zeit, wenn man mit

#define F_CPU 16000000UL

den Prozessoertakt angibt.

MFG
Falk

von Sonic (Gast)


Lesenswert?

Ups, bischen schnell abgeschickt!
Bit 0..3 sind direkt an PORTA angeschlossen, bit 4..7 an die Zeilen eine 
4x4-Matrix angeschlossen. Zum Auslesen der Spalten werden bit 4..7 auf 
Ausgang '0' gesetzt, bit 0..3 auf Eingang mit Pullup.
Bei gedrückter Taste wird das entsprechende bit mit Pullup '0'.
Zum Auslesen der Zeilen wird der Portzustand umgedreht. Das Ergebnis 
wird in eine Variable gespeichert und augewertet (in meinem Fall als 
ASCII auf UART ausgegeben).
Es können auch mehrere gleichzeitig gedrückte Tasten ausgewertet werden.

von Sonic (Gast)


Lesenswert?

@Falk:
hast du völlig Recht! Als ich das Programm geschrieben habe, hatte ich 
den _delay-Befehl noch nicht verstanden. ;-)
Sollte ich mal Ändern, war halt nur ein Testprogramm ohne Nutzen.

von johnny.m (Gast)


Lesenswert?

...und v.a. geht _delay_ms(255) bei 16 MHz CPU-Frequenz garantiert in 
die Hose, eben weil die maximale mit _delay_ms() machbare Verzögerung 
262,14 ms / F_CPU[MHz] ist und somit in diesem Falle ca. 16,4 ms...

von Falk (Gast)


Lesenswert?

@Sonic

>Es können auch mehrere gleichzeitig gedrückte Tasten ausgewertet werden.

Bist du da sicher? Weder die Hardware noch das Programm deuten darauf 
hin. Mehrere Tasten brauchen in der Matrix Dioden.

MfG
Falk

von Sonic (Gast)


Lesenswert?

>Mehrere Tasten brauchen in der Matrix Dioden.
Nein braucht's nicht, weil ich Zeilen und Spalten nacheinander abfrage. 
Hab's getestet, funktioniert.

Seid ihr damit einverstanden?
1
for(unsigned char i=0;i<=15;i++)   // Pause 15 x 10ms = 150ms (entprellung)
2
  {
3
    _delay_ms(160);    // 160/16MHz=10ms
4
  }

von Falk (Gast)


Lesenswert?

@Sonic

>>Mehrere Tasten brauchen in der Matrix Dioden.
>Nein braucht's nicht, weil ich Zeilen und Spalten nacheinander abfrage.
>Hab's getestet, funktioniert.

Glaub ich aber nicht wenn ich deinen Code sehe. Wie werden denn zwei 
(oder mehr) gedrückte Tasten an das Programm weitergegeben?

>Seid ihr damit einverstanden?

>for(unsigned char i=0;i<=15;i++)   // Pause 15 x 10ms = 150ms (entprellung)
>  {
>    _delay_ms(160);    // 160/16MHz=10ms
>  }

Nöö, aus drei Gründen.

a) Bei 16 MHz sind max. 16,4 ms drin.
b) Das Delay hat in der Routine zur Matrixauswertung nix verloren, da 
diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen 
wird.
c) Eine Verzögerung von 15 ms wird mit _delay_ms(15); generiert.

MfG
Falk

von Sonic (Gast)


Lesenswert?

Autsch! Asche auf mein Haupt!
1
for(unsigned char i=0;i<=15;i++)   // Pause 15 x 10ms = 150ms (entprellung)
2
  {
3
    _delay_ms(10);    // 10ms
4
  }

von Sonic (Gast)


Lesenswert?

>da diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen wird.
Meinst du die komplette Abfrage? Die habe ich per Polling abgefragt, das 
reicht bei den langsamen Vorgängen dicke, da brauch' ich keinen INT 
verbraten. Das _delay zwischen den Abfragen ist nötig, weil der Port 
eine gewisse Zeit braucht um die Zustände sicher anzunehmen (von Aus- 
auf Eingang umschalten, die Pullups Zu- und Abschalten)

von rudi (Gast)


Lesenswert?

ok..habt ihrs jetzt ? (spaß)...

wie sieht es denn mit meinem Code aus ? habt ihr euch den mal angeschaut 
?
man hatte mir hier folgendes geraten um meine matrix auszuwerten...

Karl heinz Buchegger (kbuchegg) wrote...

"Du hast ein Array für alle Tasten in dem für jede
Taste ein Zähler realisiert ist.
In deiner Abfrage Funktion gehst du alle Tasten (nach dem
von dir beschriebenen Prinzip) durch und wenn eine Taste
gedrückt ist, erhöhst du den Zähler. Ist die Taste nicht
gedrückt, wird der entsprechende Zähler auf 0 gesetzt.
Erreicht der Zähler 3 oder 4 (such dir was aus), dann gilt
diese Taste als gedrückt und du vermerkst dir dieses in
einem anderen Array.
Diese Abfragefunktion hängst du an einen Timer und lässt sie
alle 10 ms aufrufen.

Damit hast du funktional was ähnliches gebaut wie die PeDa
Tastenabfrage und Entprellung, nur halt angepasst an deine
Matrix.
"
Danke für die Hilfe


von Sonic (Gast)


Lesenswert?

Okay, hab' mir den Code mal angeguckt.
Zuerst muss ich sagen dass ich für eine Anwendung wie eine Tastenabfrage 
(wenn's nicht gerade eine Stoppuhr ist) keinen Interrupt benutzen würde, 
der unnötig Resourcen verbraucht. Und wenn mir in die Abfrage ein INT 
'reinfunkt, dann geht halt mal eine Abfrage in die Hose. Macht nix, 
meistens merkt man das beim Eingeben gar nicht.
Dein Code sollte eigentlich so funktionieren, ist aber etwas 
unübersichtlich und braucht seine Zeit. Abfragen wie
1
if (counter[0]||counter[1]||counter[2]||counter[3]||counter[4]||counter[5]||counter[6]||counter[7]||counter[8]||counter[9]||counter[10]||counter[11])==4)
machen das Ganze extrem langsam. Debugge das mal durch und benutze die 
Stoppuhr im AVR-Studio, dann wirst du's sehen.

von Falk (Gast)


Lesenswert?

@Sonic

>>da diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen wird.
>Meinst du die komplette Abfrage? Die habe ich per Polling abgefragt, das
>reicht bei den langsamen Vorgängen dicke, da brauch' ich keinen INT

Naja, könnte man jetzt drübr streiten. Seis drum. Dennoch würde ich den 
Delay dort rausnehemen und in die Polling-Schleife packen. Ist 
übersichtlicher und die Funktion kann einfacher wiederverwendet werden 
(auch im Interrupt wenns sein soll).

MfG
Falk


von Sonic (Gast)


Lesenswert?

Kann ich machen. Die Zeit bis zur Gültigkeit der Portzustände kann man 
auch mit einem oder mehreren NOPs machen, dürfte ausreichen. Ich 
probier's nochmal.

von Sonic (Gast)


Lesenswert?

Achso..
du meinst vermutlich die 150ms. Die Auswertung der Tasten (switch) und 
die Entprellung habe ich dort testweise untergebracht. Ist natürlich 
jedem selbst überlassen, wie er das macht. ;-)

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Siehe Anhang.

Ist ähnlich der Version in der Codesammlung (Tastenmatrix mit 2 
Drähten).


Peter

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.