Forum: Mikrocontroller und Digitale Elektronik Problem beim Auslesen einer 3x4 Tastaturmatrix


von H. G. (ledi)


Lesenswert?

Ich möchte eine 3x4 Tastenmatrix auslesen und das Ergebnis am Port C 
darstellen. Wenn ich den Code schrittweise durchsteppe, funktioniert 
alles.

Im Betrieb erhalte ich folgende Ergebnisse:
Ausgabe bei Tastendruck in der 1. Zeile = 1
Ausgabe bei Tastendruck in der 2. Zeile = 4
Ausgabe bei Tastendruck in der 3. Zeile = 7
Ausgabe bei Tastendruck in der 4. Zeile = 10

Ich habe da nun keine Idee mehr und bitte um Eure Hilfe!

Hier der C-Code:
1
/****************************************************************
2
* Einlesen der Tasten einer 3x4 Tastenmatrix          *
3
* Controller: ATMEL 90PWM316                  *
4
* Portanschlüsse der Tastenmatrix:                *
5
* Spalten:  row1=PD6, row2=PB2, row3=PB5            *
6
* Zeilen:  col1=PD5, col2=PD4, col3=PD2, col4=PD1        *
7
****************************************************************/
8
9
#include <avr/io.h>
10
#include <util/delay.h>
11
12
#define NOP();  asm volatile("nop"::);
13
14
uint8_t KeyMap[] =        // Korrektur der Tastenergebnisse
15
    { 0,                  // Anpassung an die Tastatur
16
      1, 4, 7, 10,        // 1   2   3
17
      2, 5, 8, 11,        // 4   5   6
18
      3, 6, 9, 12         // 7   8   9
19
    };                    // 10  11  12
20
21
uint8_t keyscan( void )
22
{
23
    _delay_ms(30);
24
25
  uint8_t col = 0, row = 0;
26
27
  //**** Spalten = output + low, Zeilen = input + pull up ****
28
  DDRB  =  (1<<PB2)|(1<<PB5);
29
  DDRD  =  (1<<PD6);
30
  PORTB  &=  ((0<<PB2)|(0<<PB5));
31
  PORTD  &=  (0<<PD6);
32
  PORTD    |=  (1<<PD1)|(1<<PD2)|(1<<PD4)|(1<<PD5);
33
34
    NOP();                              // wait until inputs sampled
35
  _delay_us(20);
36
    if(!(PIND & (1<<PIND5)))          // if column 1 = low
37
    {
38
      col = 4;
39
  }
40
    else if(!(PIND & (1<<PIND4)))    // if column 2 = low
41
    {
42
      col = 3;
43
  }
44
    else if(!(PIND & (1<<PIND2)))    // if column 3 = low
45
    {
46
      col = 2;
47
  }
48
    else if(!(PIND & (1<<PIND1)))    // if column 4 = low
49
    {
50
      col = 1;
51
  }
52
    
53
  if( col )                           // if column found, check row
54
  {
55
  //**** Spalten = input + pull up, Zeilen = output + low ****
56
    DDRB  &=  ((0<<PB2)|(0<<PB5));
57
    DDRD  &=  (0<<PD6);
58
    PORTB  =  (1<<PB2)|(1<<PB5);
59
    PORTD  =  (1<<PD6);
60
    DDRD  |=  (1<<PD1)|(1<<PD2)|(1<<PD4)|(1<<PD5);
61
    PORTD    &=  ((0<<PD1)|(0<<PD2)|(0<<PD4)|(0<<PD5));
62
63
      NOP();                          // wait until inputs sampled
64
    _delay_us(20);
65
      if(!(PIND & (1<<PIND6)))    // if row 1 = low
66
    {
67
         row = 5;
68
      }
69
      else if(!(PINB & (1<<PINB2)))  // if row 2 = low
70
    {
71
          row = 9;
72
      }
73
      else if(!(PINB & (1<<PINB5)))  // if row 3 = low
74
    {
75
          row = 13;
76
      }
77
    }                                   // 0 = no key
78
79
  return KeyMap [row - col];
80
}
81
82
int main (void)
83
{
84
  DDRC = 0xFF;            
85
  while(1)
86
  {
87
    PORTC = keyscan();
88
  }
89
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Wie ist die Matrix angeschlossen?

Klassisch macht man das anders. Man gibt zyklisch eine Spalte oder 
Zeile vor (Ausgabe) und schaut, welcher Pin (Eingabe) gedrückt ist. Wenn 
man dann noch die Entprellung berücksichtigt, wird's perfekt.

http://www.mikrocontroller.net/forum/codesammlung?filter=matrix*
http://www.mikrocontroller.net/forum/codesammlung?filter=tasten*

=>

Beitrag "Tasten-Matrix entprellen" (Umschreiben auf AVR!)
Beitrag "Tastenmatrix auslesen über nur 2 Leitungen" (über ADC, für 
Fortgeschrittene)

von Guido S. (flintstone)


Lesenswert?

Hallo ledi,

ich finde die Lösung klasse.
Mir ist nur aufgefallen, dass du den PortD im oberen Bereich nicht auf 
Eingang gestellt hast. Somit bleibt dieser auf Ausgang und liefert immer 
falsche Werte. Es wird somit nur beim ersten Aufruf funktionieren.

DDRD  &=  ((1<<PD1)|(1<<PD2)|(1<<PD4)|(1<<PD5));


Gruß
Guido

von H. G. (ledi)


Lesenswert?

Ja, das war auch der Fehler!
Die Register vom Port D wurden immer überschrieben.

von Heiko W. (Gast)


Lesenswert?

Hi,

Ist in dem oben aufgeführten C-Code die Tasten-Entprellung schon 
mitberücksichtigt?

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.