Habe mal ein C-Programm geschrieben, mit dem ich folgendes vorhabe... Ich habe eine Tastenblock mit 12 Tasten. (3x4 Matrix Anschluß)-->also 3 Spalten und vier Zeilen. Um das Auslesen zuz realisieren habe ich die Spalten als Eingänge mit Pull ups und die Zeilen als Ausgänge definiert. Ausgangspegel =high ("1"). Das heißt jetzt wenn ich eine Taste z.b die Zahl 3 erkennen möchte (Zeile 1 und Spalte 3) , schreibe ich am ausgang Zeile 1 eine "0" und überprüfe ob eine "0" in Spalte 3 eingelesen wird. --> Ich möchte einen 4stelligen Code eingeben... Bitte schaut euch den Code mal an. Er ist bestimmt noch optimierungswürdig... Vielen Dank für eure Hilfe @ Hannes Lux (hannes) Vielen Dank für deine Mühe, jedoch habe ich keinerlei Erfahrung mit dem Assembler und möchte das jetzt gerne in C realisieren. Habe mal ein neues Thema geöffnet, da das alte zu undurchsichtig war. THX rudi
So habe ich das gelöst:
1 | if (PINA != 15) // nur bei gedrückter Taste abfragen |
2 | {
|
3 | PORTA = 0b00001111; // Spalten abfragen |
4 | _delay_us(1); |
5 | Ergebnis = PINA; |
6 | |
7 | DDRA = 0b00001111; |
8 | PORTA = 0b11110000; |
9 | |
10 | PORTA = 0b11110000; // Zeilen abfragen |
11 | _delay_us(1); |
12 | Ergebnis += PINA; // Zeilen und Spalten verknüpfen |
13 | |
14 | DDRA = 0b11110000; |
15 | PORTA = 0b00001111; // Port-Ausgangszustand wiederherstellen |
16 | |
17 | switch (Ergebnis) |
18 | {
|
19 | case 119: T_Byte = '0'; break; // Bitmuster auswerten und Byte zuweisen |
20 | case 123: T_Byte = '.'; break; |
21 | case 125: T_Byte = '-'; break; |
22 | case 126: T_Byte = 'E'; break; |
23 | case 183: T_Byte = '1'; break; |
24 | case 187: T_Byte = '2'; break; |
25 | case 189: T_Byte = '3'; break; |
26 | case 190: T_Byte = 'C'; break; |
27 | case 215: T_Byte = '4'; break; |
28 | case 219: T_Byte = '5'; break; |
29 | case 221: T_Byte = '6'; break; |
30 | case 222: T_Byte = 'D'; break; |
31 | case 231: T_Byte = '7'; break; |
32 | case 235: T_Byte = '8'; break; |
33 | case 237: T_Byte = '9'; break; |
34 | case 238: T_Byte = 'F'; break; |
35 | default : T_Byte = ' '; break; |
36 | }
|
37 | |
38 | for(unsigned char i=0;i<15;i++) // Pause 15 x 10ms = 150ms (entprellung) |
39 | {
|
40 | _delay_ms(255); // 255ms/16MHz=16ms |
41 | }
|
42 | }
|
Vielleicht kannste was mit anfangen?
@Sonic
> _delay_ms(255); // 255ms/16MHz=16ms
Was soll das? _delay_ms() macht schon die richtige Zeit, wenn man mit
#define F_CPU 16000000UL
den Prozessoertakt angibt.
MFG
Falk
Ups, bischen schnell abgeschickt! Bit 0..3 sind direkt an PORTA angeschlossen, bit 4..7 an die Zeilen eine 4x4-Matrix angeschlossen. Zum Auslesen der Spalten werden bit 4..7 auf Ausgang '0' gesetzt, bit 0..3 auf Eingang mit Pullup. Bei gedrückter Taste wird das entsprechende bit mit Pullup '0'. Zum Auslesen der Zeilen wird der Portzustand umgedreht. Das Ergebnis wird in eine Variable gespeichert und augewertet (in meinem Fall als ASCII auf UART ausgegeben). Es können auch mehrere gleichzeitig gedrückte Tasten ausgewertet werden.
@Falk: hast du völlig Recht! Als ich das Programm geschrieben habe, hatte ich den _delay-Befehl noch nicht verstanden. ;-) Sollte ich mal Ändern, war halt nur ein Testprogramm ohne Nutzen.
...und v.a. geht _delay_ms(255) bei 16 MHz CPU-Frequenz garantiert in die Hose, eben weil die maximale mit _delay_ms() machbare Verzögerung 262,14 ms / F_CPU[MHz] ist und somit in diesem Falle ca. 16,4 ms...
@Sonic
>Es können auch mehrere gleichzeitig gedrückte Tasten ausgewertet werden.
Bist du da sicher? Weder die Hardware noch das Programm deuten darauf
hin. Mehrere Tasten brauchen in der Matrix Dioden.
MfG
Falk
>Mehrere Tasten brauchen in der Matrix Dioden.
Nein braucht's nicht, weil ich Zeilen und Spalten nacheinander abfrage.
Hab's getestet, funktioniert.
Seid ihr damit einverstanden?
1 | for(unsigned char i=0;i<=15;i++) // Pause 15 x 10ms = 150ms (entprellung) |
2 | {
|
3 | _delay_ms(160); // 160/16MHz=10ms |
4 | }
|
@Sonic >>Mehrere Tasten brauchen in der Matrix Dioden. >Nein braucht's nicht, weil ich Zeilen und Spalten nacheinander abfrage. >Hab's getestet, funktioniert. Glaub ich aber nicht wenn ich deinen Code sehe. Wie werden denn zwei (oder mehr) gedrückte Tasten an das Programm weitergegeben? >Seid ihr damit einverstanden? >for(unsigned char i=0;i<=15;i++) // Pause 15 x 10ms = 150ms (entprellung) > { > _delay_ms(160); // 160/16MHz=10ms > } Nöö, aus drei Gründen. a) Bei 16 MHz sind max. 16,4 ms drin. b) Das Delay hat in der Routine zur Matrixauswertung nix verloren, da diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen wird. c) Eine Verzögerung von 15 ms wird mit _delay_ms(15); generiert. MfG Falk
Autsch! Asche auf mein Haupt!
1 | for(unsigned char i=0;i<=15;i++) // Pause 15 x 10ms = 150ms (entprellung) |
2 | {
|
3 | _delay_ms(10); // 10ms |
4 | }
|
>da diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen wird.
Meinst du die komplette Abfrage? Die habe ich per Polling abgefragt, das
reicht bei den langsamen Vorgängen dicke, da brauch' ich keinen INT
verbraten. Das _delay zwischen den Abfragen ist nötig, weil der Port
eine gewisse Zeit braucht um die Zustände sicher anzunehmen (von Aus-
auf Eingang umschalten, die Pullups Zu- und Abschalten)
ok..habt ihrs jetzt ? (spaß)... wie sieht es denn mit meinem Code aus ? habt ihr euch den mal angeschaut ? man hatte mir hier folgendes geraten um meine matrix auszuwerten... Karl heinz Buchegger (kbuchegg) wrote... "Du hast ein Array für alle Tasten in dem für jede Taste ein Zähler realisiert ist. In deiner Abfrage Funktion gehst du alle Tasten (nach dem von dir beschriebenen Prinzip) durch und wenn eine Taste gedrückt ist, erhöhst du den Zähler. Ist die Taste nicht gedrückt, wird der entsprechende Zähler auf 0 gesetzt. Erreicht der Zähler 3 oder 4 (such dir was aus), dann gilt diese Taste als gedrückt und du vermerkst dir dieses in einem anderen Array. Diese Abfragefunktion hängst du an einen Timer und lässt sie alle 10 ms aufrufen. Damit hast du funktional was ähnliches gebaut wie die PeDa Tastenabfrage und Entprellung, nur halt angepasst an deine Matrix. " Danke für die Hilfe
Okay, hab' mir den Code mal angeguckt. Zuerst muss ich sagen dass ich für eine Anwendung wie eine Tastenabfrage (wenn's nicht gerade eine Stoppuhr ist) keinen Interrupt benutzen würde, der unnötig Resourcen verbraucht. Und wenn mir in die Abfrage ein INT 'reinfunkt, dann geht halt mal eine Abfrage in die Hose. Macht nix, meistens merkt man das beim Eingeben gar nicht. Dein Code sollte eigentlich so funktionieren, ist aber etwas unübersichtlich und braucht seine Zeit. Abfragen wie
1 | if (counter[0]||counter[1]||counter[2]||counter[3]||counter[4]||counter[5]||counter[6]||counter[7]||counter[8]||counter[9]||counter[10]||counter[11])==4) |
machen das Ganze extrem langsam. Debugge das mal durch und benutze die Stoppuhr im AVR-Studio, dann wirst du's sehen.
@Sonic >>da diese Routine sinnvollerweise periodisch im Timerinterrupt aufgerufen wird. >Meinst du die komplette Abfrage? Die habe ich per Polling abgefragt, das >reicht bei den langsamen Vorgängen dicke, da brauch' ich keinen INT Naja, könnte man jetzt drübr streiten. Seis drum. Dennoch würde ich den Delay dort rausnehemen und in die Polling-Schleife packen. Ist übersichtlicher und die Funktion kann einfacher wiederverwendet werden (auch im Interrupt wenns sein soll). MfG Falk
Kann ich machen. Die Zeit bis zur Gültigkeit der Portzustände kann man auch mit einem oder mehreren NOPs machen, dürfte ausreichen. Ich probier's nochmal.
Achso.. du meinst vermutlich die 150ms. Die Auswertung der Tasten (switch) und die Entprellung habe ich dort testweise untergebracht. Ist natürlich jedem selbst überlassen, wie er das macht. ;-)
Siehe Anhang. Ist ähnlich der Version in der Codesammlung (Tastenmatrix mit 2 Drähten). Peter
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.