Forum: Compiler & IDEs Tasten von verschiedenen Ports auslesen


von Thomas (Gast)


Lesenswert?

Hallo an Alle,

ich habe fünf Taster(aktiv-Low) deren Zustand ich gern einlesen
würde.Ist ein Taster gedrückt, soll eine Aktion ausgeführt werden.Aber
nicht solange der Taster gedrückt ist, sondern pro Tastendruck eine
Aktion(Entprellen). Als Sicherheit will ich verhindern, dass zwei
Tasten gleichzeitig gedrückt werden können.
Wie kann ich das ganze umsetzen, wenn ich nun 3 Taster an PORTD 5-7
habe und zwei an PORT 6-7?

Vielen Dank,...

Tschüß Thomas

von Thomas2. (Gast)


Lesenswert?

Mach das abfragen einfach mit ner fallenden Flanke.
Bsp:
if (bit_is_set(PIND, PIND5)
   {
    loop_until_bit_is_clear(PIND, 5);
    ...

von Thomas (Gast)


Lesenswert?

ich habe das ganze jetzt erstmal so gelöst:

if (bit is clear(PIND, PIND5) {
   ...
if (bit is clear(PIND, PIND6) {
   ...
if (bit is clear(PIND, PIND7) {
   ...
if (bit is clear(PIND, PINE6) {
   ...
if (bit is clear(PIND, PINE7) {
   ...
in der Schleife habe ich jeweils einen Counter hochgezählt zum
Entprellen.

Aber irgendwie ist das ganz schön viel Code für so ein bissl
Entprellen. Geht das nicht irgendwie einfacher?

Danke an Alle,

Thomas

von Peter D. (peda)


Lesenswert?

Man könnte die Bits zusammen fassen und dann meine Entprellroutine
(Codesammlung) nehmen:

i = (PIND >> 2) | (PINE & 0xC0); // Bit 3,4,5,6,7
i ^= ~key_state;                 // key changed ?
usw.


Peter

von Thomas (Gast)


Lesenswert?

Hi Peter,

Deine Routine habe ich mir schon angeschaut. Dabei konnte ich nicht
genau feststellen, ob das ganze über den Timer gesteuert wird oder
alles ohne Timer funktioniert. Kannst Du mir diesbezüglich vielleicht
eine kleine Erklärung geben?

Vielen Dank,

Ahoi Thomas

von Peter D. (peda)


Lesenswert?

Der Timer macht den Entprelltakt, kann aber noch für andere Sachen
benutzt werden. Das ist besser als die Zeit nutzlos zu verwarten.


Lies Dir mal den ganzen Thread in Ruhe durch, das dürfte alles
erklären.


Peter

von Thomas (Gast)


Lesenswert?

Hi Peter,

habe mir jetzt nochmal Deine Entprell-Routine angeschaut und es
versucht in meinem Programm zu realisieren. Leider entprellt es bei mir
nicht :-(! Was könnte ich also noch falsch gemacht haben?
Habe den Counter0 initialisiert und mit blinkender LED überprüft...das
geht also.
Dann habe ich Deinen Code reingehackt...dabei habe ich i= (PIND 0xE0)
|(PINE 0xC0); so gesetzt. Soll also für PIND5-7 und PINE6,7 sein.
Danach so weiter wie Du geschrieben hast.

In meiner for();; Schleife habe ich die Interrupts aktiviert(sei;) und
ne Abfrage nach meiner Taste gemacht:

if(bit_is_clear(PIND, PIND5)) {
   if(key_press)....also nur wenn Taste entprellt ist
    {...
    }}

Leider wird so nichts entprellt. Kannste mir vielleicht noch einen
Hinweis geben, was ich da noch nicht richtig verstanden habe?

Danke Thomas

von Thomas (Gast)


Lesenswert?

Hey Peter,...wo bist Du?

Hab gerade noch ein wenig probiert und bei mir ist Key_press immer 1,
wenn keine Taste gedrückt ist! Was mache ich falsch?

Danke Thomas

von Peter D. (peda)


Lesenswert?

if(bit_is_clear(PIND, PIND5)) {
   if(key_press)....also nur wenn Taste entprellt ist
    {...
    }}

Ne, doppelt gemoppelt geht nicht.

Die Routine macht alles für Dich, d.h. vergiß die Pins, lies nur
key_press aus (und setz es zurück).


Peter

von Simi (Gast)


Lesenswert?

was ist bit_is_clear ??
n makro oder was ?

von Elektrikser (Gast)


Lesenswert?

Hallo,

bit_is_clear (, );

Die Funktion bit_is_clear prüft, ob ein Bit gelöscht ist. Wenn das Bit
gelöscht ist, also auf 0 ist, wird ein Wert ungleich 0 zurückgegeben.

Diese Erklärung ist in der AVR-GCC-Einführung in der Wiki zu finden. Du
kannst auch die ganz normalen ANSI-C-Befehle verwenden
(Variable & (1<<Bitnummer)).


Gruß Elektrikser

von Elektrikser (Gast)


Lesenswert?

Das war wieder ein mieser Satzbau, aber egal.

von Thomas (Gast)


Lesenswert?

Halli hallo,

also ich habe das jetzt nochmal ausprobiert und leider habe ich das
Problem immer noch nicht lösen können. Also ich habe zur Zeit nur noch
eine Abfrage und zwar:
if(key_press) {
    ...
    key_press=0;
}
Das hat zur Folge das sofort beim Einschalten OHNE Tastendruck...die
Aktion ausgeführt wird! Und wenn ich die Taste drücke, tut sich leider
gar nichts!

Wo kann denn da jetzt noch der Fehler liegen? Ich bin mir nicht sicher
wie die Klammern zwischen den ganzen Bitoperationen gesetzt werden
müssen. Zum Beispiel in der Zeile:
ct1=ct0^ct1&i
Was hat denn da den Vorrang?

Ist die Vorinitialisierung der Variablen von Bedeutung?

Noch eine Frage, wenn ich nur noch Key_press Abfrage, dann ist es mir
ja nicht mehr möglich zu unterscheiden, welche Taste jetzt gedrückt
worden ist oder täusche ich mich da? Wenn nich, wie kann ich denn die
Tasten unterscheiden?


Wäre nett, wenn Ihr mir nochmal helfen könnt...

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Hier ist ein Beispiel, welches Du leicht auf dem STK500 ausprobieren
kannst:

http://www.mikrocontroller.net/forum/read-4-49709.html#new

Daraus geht auch hervor, wie Du die Tasten einzeln abfragst:

Danach kannst Du dann die Erweiterung auf verschiedene Ports
probieren.

Anbei die Rangfolge in C.


Peter

von Thomas (Gast)


Lesenswert?

Hi Peter,

heute Morgen habe ich mir in aller Ruhe nochmal das Schedule-Programm
angeschaut. Obwohl ich durch die vielen Funktionen nicht 100 prozentig
durchgesehen habe, konnte ich bei meinem Programm einen kleinen Erfolg
verzeichnen. Es entprellt jetzt und es erkennt die richtigen Tasten.
Nur konnte ich die Tasten noch nicht kombinieren. Dazu habe ich mal
noch ein paar leichte Fragen. Ich check das einfach mit dem
Schieboperator nicht. Ich versteh zwar Links-oder Rechtsschieben, aber
nicht in Verbindung mit folgenden Kommandos:

i=(PIND>>2)

Was wird denn dabei geschoben??? Was steht denn jetzt in i???

Deswegen versteh ich auch folgende Zeile Deines Schedule Codes nicht:

if(get_key_press(1<<PB6))...z.Bsp.

erstmal was soll (1<<PB6) bedeuten? Und zweitens PB6 ist ja ein Bit des
Datenausgangsregister und ich will doch ne Taste einlesen??? Was hat das
damit auf sich?

Falls Du mir das mal erklären kannst, kann ich bestimmt auch verstehen,
wie ich endlich die Tasten PIND5-7 und PIN6-7 auf i legen kann:

i=(PIND & 0xE0)|(PINE & 0xC0)...geht leider nicht.

werden da Bit 6 und 7 überschrieben?

Würde mich über eine Antwort sehr freuen.

Vielen Dank schon mal im Vorraus,

Ciao Thomas

von OldBug (Gast)


Lesenswert?

Hi!

Schieben (shiften) kann man mit multiplizieren (linksschieben) oder mit
dividieren (rechtsschieben) ersetzen!

i=(PIND>>2)

Hier wird der Inhalt von PIND um zwei Stellen nach rechts verschoben,
d. h., der Inhalt von PIND wird durch 4 (2**2) geteilt. Danach wird das
Ergebnis i zugewiesen.

if(get_key_press(1<<PB6))

Hier wird get_key_press(..) das Bit PB6 als Parameter übergeben.
(1 << PB6) bedeutet, daß 1 um PB6 stellen nach links geschoben wird. In
diesem Falle um 6 Stellen. Das wiederum entspricht einer Multiplikation
mit 64 (2**6).

Wenn Du verschiedene Pins von verschiedenen Ports in einer Variablen
speichern willst, dann musst Du darauf achten, daß die bits Sortiert
werden müssen und sich nicht gegenseitig überschreiben.

von Thomas (Gast)


Lesenswert?

Hey OldBug,

vielen Dank für die Erklärung...ich hoffe das habe ich soweit
verstanden.

Das mit den verschieden Pins haut bei meinem Programm leider nicht hin.
Wieso weiß ich auch nicht? Ich habe mir das jetzt so gedacht:

i=(PIND>>5)|(PINE & 0xC0);

Dann müßten die Bits 0-5 von PIND nach rechts weggeschoben werden und
der Rest mit PINE verodert werden. So das dann in i
=PINE7,PINE6,0,0,0,PIND7,PIND6,PIND5...stehen müßte oder?

CU Thomas

von Thomas (Gast)


Lesenswert?

Hey OldBug und Peter,

ich habs endlich hinbekommen!!!! Mich hat der Parameter bei
get_key_press verwirrt. Ich dachte es muß PBx sein...sozusagen was in
dem Bit steht. Aber nach der Erklärung von OldBug müßte ja zum Beispiel
(1<<PB6) gleich (1<<6) sein. Sozusagen einfach um 6 Bit geschiftet. Auf
jeden Fall habe es jetzt folgendermaßen gelößt:

i=(PIND & 0xE0)|(PINE>>3); //PIND7,PIND6,PIND5,PINE7,PINE6,...
i ^= ~key_state;
...

if(get_key_press(1<<7)) Schalter PIND7
if(get_key_press(1<<6)) Schalter PIND6
if(get_key_press(1<<5)) Schalter PIND5
if(get_key_press(1<<4)) Schalter PINE7
if(get_key_press(1<<3)) Schalter PINE6

Die ersten Tests liefen erfolgreich. Vielleicht kann mir jetzt jemand
das ganze auch noch erklären ;-)))...

Ciao Thomas

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.