www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 3x4 Tastenmatrix auslesen


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

Bewertung
0 lesenswert
nicht 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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So habe ich das gelöst:
if (PINA != 15)        // nur bei gedrückter Taste abfragen
  {  
    PORTA = 0b00001111;  // Spalten abfragen
    _delay_us(1);
    Ergebnis = PINA;
    
    DDRA = 0b00001111;            
    PORTA = 0b11110000;
    
    PORTA = 0b11110000;  // Zeilen abfragen
    _delay_us(1);
    Ergebnis += PINA;  // Zeilen und Spalten verknüpfen
    
    DDRA = 0b11110000;
    PORTA = 0b00001111;  // Port-Ausgangszustand wiederherstellen
    
    switch (Ergebnis)
      {
      case 119: T_Byte = '0'; break;  // Bitmuster auswerten und Byte zuweisen
      case 123: T_Byte = '.'; break;
      case 125: T_Byte = '-'; break;
      case 126: T_Byte = 'E'; break;
      case 183: T_Byte = '1'; break;
      case 187: T_Byte = '2'; break;
      case 189: T_Byte = '3'; break;
      case 190: T_Byte = 'C'; break;
      case 215: T_Byte = '4'; break;
      case 219: T_Byte = '5'; break;
      case 221: T_Byte = '6'; break;
      case 222: T_Byte = 'D'; break;
      case 231: T_Byte = '7'; break;
      case 235: T_Byte = '8'; break;
      case 237: T_Byte = '9'; break;
      case 238: T_Byte = 'F'; break;
      default : T_Byte = ' '; break;
      }
    
    for(unsigned char i=0;i<15;i++) // Pause 15 x 10ms = 150ms (entprellung)
      {
        _delay_ms(255);  // 255ms/16MHz=16ms
      }
  }

Vielleicht kannste was mit anfangen?

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
for(unsigned char i=0;i<=15;i++)   // Pause 15 x 10ms = 150ms (entprellung)
  {
    _delay_ms(160);    // 160/16MHz=10ms
  }

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sonic (Gast)
Datum:

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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: rudi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
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.

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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. ;-)

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

Bewertung
0 lesenswert
nicht lesenswert
Siehe Anhang.

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


Peter

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.