Da ich kein Pollingverfahren verwende, möchte ich über eine 3x4
Tastenmatrix die einzelnen Tasten über Interrupts abfragen. (Siehe
Datei)
Die 3 Spalten sind mit den Interruptpins Int0, Int1 und Int2 des
Controllers verbunden. Die 4 Zeilen mit den Pins PC4...PC7.
Spaltenpins = als Eingänge geschaltet
Zeilenpins = als Ausgänge geschaltet
Die 3 Spalten ergeben sich über die einzelnen Interrupts. Wie mache ich
das aber am einfachsten mit den Zeilen?
Hier der C-Code:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
#include<avr/wdt.h>
5
#include<avr/sleep.h>
6
7
intmain(void)
8
{
9
DDRC=(1<<PC4)|(1<<PC5)|(1<<PC6)|(1<<PC7);// Datenrichtung der Zeilen = Ausgang
10
DDRD=(0<<PIND6);// Datenrichtung Eingang (für Int 0)
11
DDRB=(0<<PINB2)|(0<<PINB5);// Datenrichtung Eingang (für Int 1, Int 2)
Heimo G. schrieb:> Da ich kein Pollingverfahren verwende
Warum nicht?
Man hat doch eh meistens nen Timerinterrupt am Laufen.
> Die 3 Spalten ergeben sich über die einzelnen Interrupts. Wie mache ich> das aber am einfachsten mit den Zeilen?
Indem Du im Timerinterrupt abfragst und entprellst.
Peter
> Da ich kein Pollingverfahren verwende, möchte ich über eine 3x4> Tastenmatrix die einzelnen Tasten über Interrupts abfragen
Dann polle die Tastatur in einem Timerinterrupt.
Peter Dannegger schrieb:> Heimo G. schrieb:>> Da ich kein Pollingverfahren verwende>> Warum nicht?> Man hat doch eh meistens nen Timerinterrupt am Laufen.
Da ich die Schaltung über Akkus betreiben möchte, soll der Controller
"schlafen", wenn kein Tastendruck erfolgt.
>>> Die 3 Spalten ergeben sich über die einzelnen Interrupts. Wie mache ich>> das aber am einfachsten mit den Zeilen?>> Indem Du im Timerinterrupt abfragst und entprellst.>
Genau hier habe ich das Problem (Bin noch Anfänger)!
Wie genau mache ich das?
>> Peter
> Da ich die Schaltung über Akkus betreiben möchte, soll der Controller> "schlafen", wenn kein Tastendruck erfolgt.
PC4-PC7 auf Low, PullUps an INT0-INT2 einschalten,
und schlafen gehen, auf Interrupts (durch fallende
Flanke bzw. oft zwingt einen der uC Hersteller zu
low-Pegel) warten.
Beim aufwachen nach einem Interrupt mit PC4-PC7
herausfinden, welches Taste es nun war.
MaWin schrieb:>> Da ich die Schaltung über Akkus betreiben möchte, soll der Controller>> "schlafen", wenn kein Tastendruck erfolgt.>> PC4-PC7 auf Low, PullUps an INT0-INT2 einschalten,> und schlafen gehen, auf Interrupts (durch fallende> Flanke bzw. oft zwingt einen der uC Hersteller zu> low-Pegel) warten.>
OK! Das ist mir klar!
> Beim aufwachen nach einem Interrupt mit PC4-PC7> herausfinden, welches Taste es nun war.
Und hier habe ich das Problem!
Wie finde ich heraus, welche Taste nun gedrückt wurde?
Hallo Peter!
Erstmal vielen Dank für Deine Hilfe!
Ich habe nun den Code für meine Anwendung eingebaut.
Soweit funktioniert das auch, wobei der in der Funktion zurückgegebene
Wert nicht mit meiner Tastatur übereinstimmt. (Siehe Bild: Die roten
Ziffern werden berechnet).
Wie baue ich das am am einfachsten um?
Weiters möchte ich die Funktion in eine Interruptroutine einfügen. D.h,
egal, welche Taste ich drücke soll der Int. ausgelöst werden. Ich möchte
hier aber nur einen einzigen Int. verwenden. Geht das?
Heimo G. schrieb:> Soweit funktioniert das auch, wobei der in der Funktion zurückgegebene> Wert nicht mit meiner Tastatur übereinstimmt. (Siehe Bild: Die roten> Ziffern werden berechnet).> Wie baue ich das am am einfachsten um?
Da sind offenbar Zeilen mit Spalten vertauscht. Das könnte man jetzt im
Code entsprechend umbauen.
Oder aber men benutzt ganz einfach einen Mapping-Array um das Mapping
richtig zu stellen.
1
uint8_tKeyMap[]=
2
{0,
3
'1','4','7','*',
4
'2','5','8','0',
5
'3','6','9','#'
6
};
7
8
9
uint8_tkeyscan(void)
10
{
11
....
12
13
returnKeyMap[row-col];
14
}
Ob du da jetzt im Mapping Array die Tasten als Tastennummer oder aber
(so wie ich jetzt) als Zeichen einträgst, musst du entscheiden. Im
Grunde ist es einfach nur ein Array, in das du mit deiner ermittelten
Nummer reingehst und welches dir sagt, welche Taste dann vorliegt. Wie
die Einträge aussehen müssen hab ich mir aus deinem Bild abgeleitet. Die
in deinem Bild rote Zahl ist die bisherige Nummer, so wie sie von
keyscan bis jetzt ermittelt wurde. Da ich die als Index in das Array
nehme, sagt mir das Bild, was an dieser Position im Array abgelegt sein
muss.
Als Anmerkung: Die AVRs haben (meist?) auch einen Pin-Change-Interrupt.
Vorteil: Man "verschwendet" nicht INT0-2 und es wären auch mehr als drei
Spalten möglich.
> Da sind offenbar Zeilen mit Spalten vertauscht. Das könnte man jetzt im> Code entsprechend umbauen.> Oder aber men benutzt ganz einfach einen Mapping-Array um das Mapping> richtig zu stellen.>>
1
>uint8_tKeyMap[]=
2
>{0,
3
>'1','4','7','*',
4
>'2','5','8','0',
5
>'3','6','9','#'
6
>};
7
>
8
>
9
>uint8_tkeyscan(void)
10
>{
11
>....
12
>
13
>returnKeyMap[row-col];
14
>}
15
>
SUPER!!!
Funktioniert einwandfrei!
Hast du auch eine Idee, wie ich das ganze nun in einer
Interruptserviceroutine so verpacke, dass ich mit einem einzigen
Interrupt auskomme?
Ich verwende den ATMEL 90PWM316 und der hat keinen Pin-Change-Interrupt.