mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 3x4 Matrixtastatur an ATmega8


Autor: Christoph Borowski (cborowski)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
void init_ports(void) {
  // PD0-PD6 als Eingänge schalten.
  DDRD &= ~((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
  // PD0-PD2 mit internen Pullups, da diese dauerhaft Eingänge sind.
  PORTD |= ((1<<PD0) | (1<<PD1) | (1<<PD2));
  // PD3-PD6 ohne interne Pullups, da diese nacheinander als Ausgänge geschaltet werden.
  PORTD &= ~((1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
}

int8_t getKeyInput() {
  for (int col=3; col<7; col++) {
    // nacheinander die Eingänge PD3-PD6 als Ausgang schalten
    DDRD |= (1 << col);
    for (int row=0; row<3; row++) {
      // nacheinander die Eingänge überprüfen
      // falls low  => Taste gedrückt
      // falls high => Taste nicht gedrückt
      if (!(PIND & (1 << row))) {
        return (row + 1) + ((col-3) * 3);
      }
    }
    // Ausgang wieder auf Eingang schalten
    DDRD &= ~(1 << col);
  }
}

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?

Autor: loool (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Christoph Borowski (cborowski)
Datum:

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

Autor: Christoph Borowski (cborowski)
Datum:

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

Autor: Michael (Gast)
Datum:

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

Autor: Christoph Borowski (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Andreas W. (Gast)
Datum:

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

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.