Einen schönen Abend zusammen, ich habe an meinem ATmega328 eine 3x4 Tastaturmatrix und verwende hierzu die Entprellung vom Peter Dannegger -> Beitrag "Re: Tastatur Matrix entprellen" Meine Dateien sind im Anhang. Timer in der Main wird gestartet. Wenn ich nur einen Spalte auslese funktioniert alles und dieser Tastendruck wird auch erkannt. (Nur einen Spalte in der Funktion keyscan() aktiviert - rest auskommentiert). Wenn ich nun alle drei Spalten abfrage, dann werden auch immer die Taste(n) der folgenden benachtbarte Reihe mit angezeigt. Mit schein so, dass ich hier eine Kleinigkeit zur Trennung der Tasten übersehen habe... Kann mir hier jemand kurz auf die Sprünge helfen ? Viele Grüße, Mia
Mia schrieb: > Kann mir hier jemand kurz auf die Sprünge helfen ? Das einzige was mir auffällt: Du schiebst um 1, 5, 9, erwartest aber KEY0 bei bit 0.
Ja... Ich werte aber key0 nicht aus und will eigentlich die Zählweise wie beim Telefon mit 1 beginnen
Naja. Vergleiche mal die Definitionen, insbesondere von ROWX und wie sie mit den Schiebeooperationen zusammenhängen. Im Code hier Beitrag "Re: Tastatur Matrix entprellen" sind es PB0 und PB2, die dann um 1 verschoben werden, was beim Auslesen der zweiten Reihe direkt addiert (verodert) werden kann. Bei deinen Definitionen liegen die Reihen direkt nebeneinander. Du musst also andere Schiebeoperationen nehmen. Du hast dagegen einfach immer wieder 4 addiert, was natürlich im Getriebe knirscht.
Mia schrieb: > Ja... Ich werte aber key0 nicht aus und will eigentlich die Zählweise > wie beim Telefon mit 1 beginnen Das ist doch völlig Wurst. Ignoriere das erstmal.
Klaus schrieb: > Naja. Vergleiche mal die Definitionen, insbesondere von ROWX und > wie sie > mit den Schiebeooperationen zusammenhängen. > > Im Code hier Beitrag "Re: Tastatur Matrix entprellen" sind > es PB0 und PB2, die dann um 1 verschoben werden, was beim Auslesen der > zweiten Reihe direkt addiert (verodert) werden kann. > > Bei deinen Definitionen liegen die Reihen direkt nebeneinander. Du musst > also andere Schiebeoperationen nehmen. Du hast dagegen einfach immer > wieder 4 addiert, was natürlich im Getriebe knirscht. Falls ich hier einen denkfehler in der Zuordnung gemacht habe, dann kann man das ja noch in der Definition anpassen. Ich habe halt die Schiebeoperation mir so überlegt... 1. COL0 auf Masse und die ROW einlesen -> 1 schieben, das sind dann die Bits 1 bis Bit 4 von der Variable val 2. CLO1 auf Masse und die ROW einlesen -> 4 schieben -> das sind dann die Bits 5 bis Bit 9 von der Variable Val 3. CLO2 auf Masse und die ROW einlesen -> 9 schieben -> das sind dann die Bits 10 bis Bit 14 von der Variable Val Wenn ich in meiner Funktion nur eine Spalte auslese - z.B. so
1 | static uint16_t keyscan(void) |
2 | {
|
3 | uint16_t val; |
4 | |
5 | |
6 | DDRC &= ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs |
7 | DDRD &= ~(COL0 | COL1 | COL2 ); // Inputs |
8 | PORTC |= ROW0 | ROW1 | ROW2 | ROW3; // with pullup |
9 | PORTD |= COL0 | COL1 | COL2; // with pullup |
10 | PORTD &= ~COL0; // Low |
11 | DDRD |= COL0; // Output |
12 | NOP(); // load Input latch ! |
13 | val = (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 1; |
14 | |
15 | */
|
16 | DDRC &= ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs |
17 | DDRD &= ~(COL0 | COL1 | COL2 ); // Inputs |
18 | PORTC |= ROW0 | ROW1 | ROW2 | ROW3; // with pullup |
19 | PORTD |= COL0 | COL1 | COL2; // with pullup |
20 | PORTD &= ~COL1; // Low |
21 | DDRD |= COL1; // Output |
22 | NOP(); // load Input latch ! |
23 | val |= (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 5; |
24 | */
|
25 | /*
|
26 | DDRC &= ~(ROW0 | ROW1 | ROW2 | ROW3); // Inputs
|
27 | DDRD &= ~(COL0 | COL1 | COL2 ); // Inputs
|
28 | PORTC |= ROW0 | ROW1 | ROW2 | ROW3; // with pullup
|
29 | PORTD |= COL0 | COL1 | COL2; // with pullup
|
30 | PORTD &= ~COL2; // Low
|
31 | DDRD |= COL2; // Output
|
32 | NOP(); // load Input latch !
|
33 | val |= (PINC & (ROW0 | ROW1| ROW2 | ROW3)) << 9;
|
34 | */
|
35 | |
36 | return val; |
37 | }
|
..dann fuktioniert es. Ich habe nur das Problem mit der Erkennung der benachtbarten Tasten - hängt das auch mit der Schiebeoperation zusammen ? Mia
Tja. Schau' Dir den Code einfach mal im Debugger oder Simulator genau an, was er tut. Man muss Dir zugute halten, das Peter Danneggers Codes manchmal so ausgefuchst sind, das man so ein oder zwei Facepalms braucht, bis es klingelt. Ist mir auch schon so gegangen - bis zum Zweifel ob das eigentlich ein Qualitätsmerkmal ist oder eine Manieriertheit. Ich bin offen gesagt gerade zu faul, das selbst zu machen. Ich würde an Deiner Stelle mal genau schauen was denn nun:
1 | a |= b << c; |
insbesondere durch den Vorrang der Operatoren, bedeutet. Das ist halt so ein Problem wenn man so ein Programm nur nach Mustervergleich erweitert, ohne es zu verstehen. :-) Bei Kochrezepten geht das eher (bin selber ein Hobbykoch), aber in der Software nicht (immer).
Dein Problem kann auch an der Schaltgeschwindigkeit beim Umschalten der einzelnen Reihen liegen. Drück einfach mal zwei nicht in Spalte nebeneinander liegende Tasten und lass dir das Ergebnis anzeigen. Schaltest du zu schnell um, dann erscheint die Taste der ersten Reihe quasi wie ein Schatten in der nächsten Reihe. (ist durch Debuggen/Simulieren nicht so einfach erkennbar) Ich hatte das Problem mal bei einem FPGA-Board, bei dem ich dann mit der Abfragefrequenz bis in den "sicheren" Bereich runtergegangen bin.
Sigi schrieb: > Dein Problem kann auch an der Schaltgeschwindigkeit > beim Umschalten der einzelnen Reihen liegen. > Drück einfach mal zwei nicht in Spalte nebeneinander > liegende Tasten und lass dir das Ergebnis anzeigen. > Schaltest du zu schnell um, dann erscheint die > Taste der ersten Reihe quasi wie ein Schatten in > der nächsten Reihe. (ist durch Debuggen/Simulieren > nicht so einfach erkennbar) > > Ich hatte das Problem mal bei einem FPGA-Board, bei > dem ich dann mit der Abfragefrequenz bis in den > "sicheren" Bereich runtergegangen bin. Das Problem sind nicht zwei Tasten die nacheinander gedrückt werden, sonder das Ein Tastendruck als zwei interpretiert werden - die eigentliche Taste plus deren nachbar. Ich werde das mal am debugger nachvollziehen... mia
Das wird im Debugger schwierig werden. Am Code seh ich erst mal nichts auffälliges. Vorschlag: Du hast ein Programm, bei dem du irgendwo die gedrückte Taste sehen kannst. und zwar alle 12. Gut. Wenn du im Code nur die erste Spalte aktivierst und alle anderen auskommentierst, kriegst du dann bei einem Tastendruck auf einer Taste die NICHT in dieser Spalte liegt auch eine Ausgabe? Oder kriegst du nur die jeweils richtige Taste gemeldet? Wenn du reihum dann nacheinander jeweils eine andere Spalte aktivierst, stimmt dann jeweils die Tastenzuordnung? Wenn das bei einzeln aktivierten Spalten funktioniert, dann hast du tatsächlich ein Problem mit dem schnellen Umschalten zur nächsten Spalte. Ev. sind da irgendwelche Kapazitäten im Spiel, die nicht schnell genug umgeladen werden können. Du könntest das zb so zu lösen versuchen, dass du pro KeyTimerEvent Aufruf nicht das komplette Tastenfeld abscannst, sondern immer nur 1/3. Reihum das jeweils nächste Drittel (die nächste Spalte). Bei halbwegs moderatem Aufruf der KeyTimerEvent sollte das von der Haptik noch immer kein Problem sein.
:
Bearbeitet durch User
Mia schrieb: > Das Problem sind nicht zwei Tasten die nacheinander gedrückt werden, > sonder das Ein Tastendruck als zwei interpretiert werden - die > eigentliche Taste plus deren nachbar. Aber das habe ich doch mit meinem Beispiel gemeint: Du drückst eine Taste einer Reihe und dein Programm zeigt die Taste in den zwei benachbarten Zeilen an. Wenn du 2 bzw. 3 "diagonale" Tasten drückst, siehst du die "Schatten" bzw. die Mehrfachaktivierung am deutlichsten, und zwar für alle Reihen parallel. Das Hauptproblem liegt hier an der Umschalt- Geschwindigkeit. In einer IRQ-Routine schaltest du auf alle Reihen um und fragst auch noch ab. Schalte doch statt dessen folgendermassen um: 1. IRQ: 1. Reihe anschalten 2. IRQ: 1. Reihe abfragen 3. IRQ: 1. Reihe abschalten 4. IRQ: 2. Reihe anschalten 5. IRQ: 2. Reihe abfragen .. etc .. und das mit z.B. 1 kHz Timer-IRQ. Damit gibst du deiner Tastaturmatrix zwschen je anschalten/abfragen und abschalten genug Zeit zum einpendeln. Und genau das war bei mir auch das Problem, hab's mit dem Oszi nachgemessen und die "Schatten" beobachten können. Nur mit einer Simulation hätte ich das nie entdeckt.
Alternativ könnte man auch einmal probieren, hier
1 | NOP(); // load Input latch ! |
einen 'Arsch voll' NOPS einzufügen. Natürlich nur zu Probezwecken:-)
Karl H. schrieb: > einen 'Arsch voll' NOPS einzufügen. Natürlich nur zu Probezwecken:-) gute Idee zum Rumprobieren, hab's beim ersten Mal auch so gemacht. Soweit ich mit noch erinnere, lag die max. umschaltfrequenz deutlich unter 100 kHz.
Hallo, bin heute endlich wieder mal zum testen gekommen. Die gnazen NOPs und auch ein Delay hat hier niht gebracht. Habe nun die Lösung von fritzler-avr.de im Einsatz - sieht bis jetzt ganz gut aus.. Danke für das Suchen nach dem Problem Mia
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.