Forum: Mikrocontroller und Digitale Elektronik 3x4 Matrixtastatur an ATmega8


von Christoph B. (cborowski)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe die SAMWELL-Tastatur von Pollin etwas umgearbeitet, so dass ich 
sie als 'normale' 3x4 Matrixtastatur nutzen kann. Nun habe ich die 
Tastatur an Port D gehängt (siehe angehängte Grafik) und versuche sie 
gemäß dem folgenden C-Code abzufragen:
1
void init_ports(void) {
2
  // PD0-PD6 als Eingänge schalten.
3
  DDRD &= ~((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
4
  // PD0-PD2 mit internen Pullups, da diese dauerhaft Eingänge sind.
5
  PORTD |= ((1<<PD0) | (1<<PD1) | (1<<PD2));
6
  // PD3-PD6 ohne interne Pullups, da diese nacheinander als Ausgänge geschaltet werden.
7
  PORTD &= ~((1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
8
}
9
10
int8_t getKeyInput() {
11
  for (int col=3; col<7; col++) {
12
    // nacheinander die Eingänge PD3-PD6 als Ausgang schalten
13
    DDRD |= (1 << col);
14
    for (int row=0; row<3; row++) {
15
      // nacheinander die Eingänge überprüfen
16
      // falls low  => Taste gedrückt
17
      // falls high => Taste nicht gedrückt
18
      if (!(PIND & (1 << row))) {
19
        return (row + 1) + ((col-3) * 3);
20
      }
21
    }
22
    // Ausgang wieder auf Eingang schalten
23
    DDRD &= ~(1 << col);
24
  }
25
}

Die Funktion init_ports() wird am Anfang aufgerufen, die Funktion 
getKeyInput() jede Sekunde einmal.

Funktionsweise von getKeyInput():

- PD3 als Ausgang schalten
- nacheinander PD0-PD2 abprüfen, ob diese low sind => wenn ja, dann 
Taste 1, 2 oder 3 gedrückt
- PD3 wieder als Eingang

- PD4 als Ausgang schalten
- nacheinander PD0-PD2 abprüfen, ob diese low sind => wenn ja, dann 
Taste 4, 5 oder 6 gedrückt
- PD4 wieder als Eingang

Und das ganze dann noch mit PD5-PD6, so dass die Tasten 7-9, 0 und down 
& up abgeprüft werden.

Das ganze funktioniert, aber wenn ich eine Taste länger gedrückt lasse, 
dann habe ich ein interessanten Effekt. Z. B. wird die Taste 5 länger 
als 1 Sekunde gedrückt. Dann gibt mir die Funktion zuerst 5 zurück und 
anschließend immer wieder eine 2. Das gleiche gilt für die Taste 8 & 0.
Bei der Taste 7 wird zuerst die 7 und anschließend immer die 1 
zurückgegeben.
Man kommt relativ schnell drauf, dass anschließend der Wert der Taste 
zurückgegeben wird, die sich in der gleichen Reihe wie die gedrückte 
Taste befindet, aber halt in der ersten abgefragten Spalte (für die 
Zahlen 1, 2 & 3).

Kann mir das jemand bitte erklären?

von loool (Gast)


Lesenswert?


von Peter D. (peda)


Lesenswert?

Christoph Borowski wrote:

> Die Funktion init_ports() wird am Anfang aufgerufen, die Funktion
> getKeyInput() jede Sekunde einmal.

Würde mir nicht gefallen. Ich bin eher ein Kurzdrücker und würde daher 
die Tastatur irgendwann zerdreschen, weil sie nicht reagiert.
Das Abfrageintervall sollte nicht größer 200ms sein (Bei Entprellung 
noch um den Entprellfaktor weniger).


> Das ganze funktioniert, aber wenn ich eine Taste länger gedrückt lasse,
> dann habe ich ein interessanten Effekt. Z. B. wird die Taste 5 länger
> als 1 Sekunde gedrückt. Dann gibt mir die Funktion zuerst 5 zurück und
> anschließend immer wieder eine 2.

Daß sie nach jeder Abfrage was zurück gibt, ist klar, sie hat ja keine 
Flankenerkennung.

Daß es unterschiedliche Werte sind, dürfte an der Hardware oder den 
anderen Programmteilen liegen.

Der Code ist zwar nicht optimal (int (16Bit), Multiplikation, variables 
Schieben ohne Not), sieht aber o.k. aus.


Peter

von Christoph B. (cborowski)


Lesenswert?

@loool

Zwei Dinge fallen mir dazu ein:

1. Wenn man keine Ahnung hat, dann sollte man die Klappe halten... hier 
eher die Tastatur in Ruhe lassen.

2. Wenn man Ahnung hat & diese nicht weitergeben will... gleich 
Schlussfolgerung wie in Punkt 1

Un wem die Intelligenz fehlt 1 & 2 zu verstehen: Schwachsinnige Beiträge 
braucht hier kein Mensch!

Gruss
Christoph

von Christoph B. (cborowski)


Lesenswert?

Peter Dannegger wrote:
> Christoph Borowski wrote:
>
>> Die Funktion init_ports() wird am Anfang aufgerufen, die Funktion
>> getKeyInput() jede Sekunde einmal.
>
> Würde mir nicht gefallen. Ich bin eher ein Kurzdrücker und würde daher
> die Tastatur irgendwann zerdreschen, weil sie nicht reagiert.
> Das Abfrageintervall sollte nicht größer 200ms sein (Bei Entprellung
> noch um den Entprellfaktor weniger).

Die Abfrage ist nur zu Testzwecken eingebaut, um die Funktion 
getKeyInput() zu testen. Wird natürlich nicht so bestehen bleiben.


>> Das ganze funktioniert, aber wenn ich eine Taste länger gedrückt lasse,
>> dann habe ich ein interessanten Effekt. Z. B. wird die Taste 5 länger
>> als 1 Sekunde gedrückt. Dann gibt mir die Funktion zuerst 5 zurück und
>> anschließend immer wieder eine 2.
>
> Daß sie nach jeder Abfrage was zurück gibt, ist klar, sie hat ja keine
> Flankenerkennung.

Das ist nicht das Problem. Mir ist schon klar, dass beim längeren 
Drücken jede Sekunde ein Wert zurückgeliefert wird. Die Frage ist, wieso 
der erste Wert stimmt, die folgenden aber nicht?

> Daß es unterschiedliche Werte sind, dürfte an der Hardware oder den
> anderen Programmteilen liegen.

Aus viel mehr Software besteht das ganze nicht. Es gibt eine 
Endlosschleife, aus der die Funktion jede Sekunde einmal aufgerufen 
wird. Die ermittelte Taste wird auf dem Display ausgegeben.

> Der Code ist zwar nicht optimal (int (16Bit), Multiplikation, variables
> Schieben ohne Not), sieht aber o.k. aus.

Das mit dem int ist mir auch gerade aufgefallen.

Ok, Danke für das Drübergucken... vielleicht fällt mir selbst der Grund 
für das Verhalten auf.

Gruss
Christoph


> Peter

von Michael (Gast)


Lesenswert?

hallo christoph.

du verläßt die funktion (return) ohne den ausgang wieder als eingang 
geschaltet zu haben.
im nächsten durchlauf ist dann der "row"-pin schon bei der ersten 
"col"-abfrage LOW.

also:
- du drückst 5
- du schaltest PD3 als ausgang -> es tut sich nix, weil du ja 5 drückst
- du schaltest PD4 als ausgang -> du hast LOW an PD1
- du verläßt die funktion OHNE PD3 und PD4 wieder als eingang zu setzen!
- du rufst die funktion erneut auf
- du fragst PD3 ab
- PD1 ist immer noch LOW, weil PD4 immer noch ausgang ist
- du kriegst 2 zurück

alles klar?

gruß

michael

von Christoph Borowski (Gast)


Lesenswert?

Hallo Michael, hallo zusammen,

oh man, darauf hätte ich auch selbst kommen MÜSSEN! Wieder mal ein 
Fall von 'Man sieht den Wald vor lauter Bäumen nicht'.

Ok, vielen Dank... jetzt suche ich mir eine Zimmerecke zum Schämen aus 
;)

Gruss
Christoph

von Peter D. (peda)


Lesenswert?

Ja, das sind so die Fallstricke eines Return mitten im Code.


Ich würde die Initialisierung nicht extra machen, sondern immer vorne im 
Aufruf. Dann ist das Problem weg.
Und die paar Zyklen mehr fallen bei der vielen variablen Schieberei 
(1<<i) nicht ins Gewicht.


Peter

von Andreas W. (Gast)


Lesenswert?

außerdem solltest du darauf achten das du auf alle fälle ein wert 
zurückgibst. also auch wenn keine taste gedrückt ist.

ich bin eigendlich auch Fan davon funktionen auch mittendrin mit einen 
return zu verlassen. Es erfordert aber auch längeres nachdenken :(

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.