Forum: Compiler & IDEs taster auf 2 arten abfragen


von lordchen (Gast)


Lesenswert?

moin !
ich habe 8 taster an dem port d angeschlossen
diese taster möchte ich auf zwei verschiedene methoden auslesen:

1. normal ob er gedrücktist (entprellen)
2. ob er für mind. 3 sekunden gedrückt ist.

ich hab schon einiges gelesen und leute genervt und trotzdem weiß ich 
noch nicht wie ich es anstellen soll - habe mir jetzt folgendes 
überlegt:

ich mache einen interrupt der alle 50ms ausgeführt wird
(der µC läuft bei 1Mhz)

am anfang dieses int's ist eine große schleife die abfragt:

ist t1 or  t2 or t3 or t4 or t5 or t6 or t7 or t8 gedrückt ??
nein: interrupt beenden und zu main zurückkehren
ja: dann kommt eine switch anweisung die herausfindet WELCHER der taster 
gedrückt ist
Case t1  Case t2 Case t3 Case t4 ... ...

In jeder sieser case blöcke steht jetzt:
eine kleine schleife  zum entprellen die 65025 zyklen nachschaut ob der 
jeweilige taster gedrückt ist bzw bleibt.
DANACH könnte man den druck ja schon als kurzen tastendruck 
intapretieren aber es soll ja weiterhin überürüft werden ob es nicht im 
einen langer tastendruck (3 sekunden) handelt.
also soll der zähler  jetzt weiter hochzählen bis 3millionen (3sekunden 
bei 1MHz) wird der taster beim inkrementieren zwischen 65.025 und 
3.000.000 unterbrochen (durch loslassen) wird der interrupt unterbrochen 
und zur funktion t1_kurz gewechselt
hat der zähler 3.000.000 erreicht wird der interrupt auch unterbrochen 
und zur funktion t1_lang gewechselt

1. kann man das so machen, mus sich dabei was besonderes beachten oder 
gibt es da intelligentere lösungen ?!

2. als was muss ich eine variable deklarieren um die bis 3.000.000 
hochzählen zukönnen ?

viele grüße
 lordchen

von Joerg Wunsch (Gast)


Lesenswert?

1.) Man kann das vielleicht so machen... s. u.

2.) uint32_t, die geht bis 4 Milliarden

Erstens sollte man Interruptfunktionen so knapp wie möglich
halten.  Also keinesfalls ellenlange Warteschleifen dort
hineinbringen.  Zweitens, wenn Du sowieso einen Zeitgeber
benutzt, dann laß ihn doch einfach nur den Status der Tasten
abfragen, wie er gerade ist, und schreibe das in einer Art
FIFO hintereinander auf (für alle Tasten).  In der Auswertung
(die ggf. noch im Interrupt erfolgen kann oder auch außerhalb)
siehst Du nach, ob eine bestimmte Taste mittlerweile 3 mal
denselben Zustand hatte und ob der zuletzt germerkte ausgewertete
Zustand vom derzeitigen differiert.  Wenn ja, dann hast Du eine
Flanke erkannt (Taste gedrückt oder losgelassen).

Abfrageintervall würde ich auf 10 ms legen, mit 3 Abfragen
hättest Du dann die Entprellung.

Wenn Du Dir außerdem noch die ,,absolute Zeit'' mitmeißelst,
an der Du die letzte Flanke erkannt hast, dann kannst Du
später auch noch feststellten, ob die Taste ,,lange'' gedrückt
worden ist (durch Vergleich der aktuellen Zeit mit der gemerkten).
Mit ,,absoluter Zeit'' meine ich dabei die einfach mitgezählten
timer ticks, sinnvollerweise wohl auch in einem uint32_t (pro
Taste) gemerkt.  Bei 10 ms hast Du dann einen Überlauf von
497 Tagen, d. h. nach 497 Tagen Laufzeit wirst Du die lange
gedrückte Taste nicht mehr erkennen, wenn sie just vor dem
Überlauf gedrückt worden ist.  Das war mal irgendwann die
Maximaldauer, die man ein Linux am Stück laufen lassen konnte,
weil danach die ,,jiffies'' übergelaufen sind, die dazumals
von vielen Treibern als Kriterium benutzt worden sind.  Gleicher
Bug war im Win95, nur daß dort der Zeitgeber mit 1 ms tickt,
so daß nach 49,7 Tagen der Mauszeiger nicht mehr reagierte...
Es hat bezeichnenderweise mehrere Jahre gedauert, bis dieser
Bug bekannt geworden ist, d. h. der Großteil der Win95 hat
diese uptime ohnehin nie erreicht. ;-)

von lordchen (Gast)


Lesenswert?

hmm also  du meinst
alle 10ms wird der int. ausgelöst

in der int-funktion wird bei jedem aufruf  nachgesehen welche taster 
gedrückt sind
also für jeden taste eine variable und jedesmal wenn der int einen 
gedrückten taster feststellt wird die dazugehörige variable z.B: taster1 
um eins incrementiert
beim 3. int stellt er fest oh taster1 = 3; dann führt er die 
funktion_taster1_kurz  aus , setzt alle tasterX-Variablen af 0 und 
beendet den interrupt
wird taster1 durchgehend gedrückt hat der interrupt die variable taster1 
nach 4 sekunden  auf 400 hochgezählt (400  * 10ms = 4Sekunden)
Wenn also taster1=400 wird funktion_taster1_lang ausgeführt
Mit einer 32bit variablen kann man bis 4.294.967.295 zählen aber ich 
brauch doch nur bis 400 oder nicht ? .. verstehe das nicht !???

aber das gesamtergebnis der taster abfrage soll aber nur ein 
garkeintaster gedrückt / tasster C lang gedrückt oder taster x kurz 
gedrückt sein
denn es soll davon ausgegangen werden, das nur ein taster gleichzeitig 
grdrückt wird... wie muss man das anstelen ?.

von Peter D. (peda)


Lesenswert?

Guckst Du mal Codesammlung:

http://www.mikrocontroller.net/forum/read-4-16594.html


Da ist ein "C_tast.c51" von mir mit Repeat-Funktion, wenn eine Taste 
länger gedrückt ist.


Peter

von lordchen (Gast)


Lesenswert?

COOL danke das klappt auch ... die hex zumindest

wennich die C datei hex-en will bekomm ich den fehler:

seit der neien AVR-GCC version muss man ja /avr angeben ... das hab ich 
schon gemacht
aber danngibt es noch fehler, bei denen ich leider nicht weiter komme :

D:\Mikrocontroller\entprell>compile.bat

D:\Mikrocontroller\entprell>C:\WinAVR\bin\avr-gcc-mmcu=at90s8515 -Os -o 
kofi.out kofi.c
kofi.c:39: error: syntax error before "char"
kofi.c:40: error: syntax error before "char"
kofi.c:107: error: `TIMER0_OVF0_vect' undeclared here (not ina function)
kofi.c:107: error: parse error before "timer0_int"
kofi.c: In function `main':
kofi.c:118: warning: return type of `main' is not `int'

kann mir da einer helfen sonst kann ich mit dem programm leider nichts 
anfangen ;-((

danke schonmal im vorraus

von lordchen (Gast)


Angehängte Dateien:

Lesenswert?

hab die teil-angepasste file vergessen ..bin mir auh nichtganz sicher ob 
das wasich da verändert hab richtig ist auf jedenfall gibts schonmal 
weniger fehler  *g*g*

von lordchen (Gast)


Lesenswert?

OK also mit peters debouncerkannich nix anfangentrotzdem danke !

mein programm machtzwar fortschritte funzt aber immernoch nicht !

ich weiß nicht wie ich das jezt machen soll

SIGNAL(SIG_OVERFLOW1)
{
if(~PIND & 1)
  {
    t1++;
      if (t1 == 3)
      {
        t1 = 0;
        lcd_clrscr();
          lcd_puts(" Taster 1 ");
        delay();
        delay();
      }

      if (t1 == 10)
      {
        t1 = 0;
        lcd_clrscr();
        lcd_puts("=Taster 1=");
        delay();
        delay();
      }
  }

  else
  {

  }

TCNT1  = 0xfd24;

}


Also das die sequwnz wo t1 10 wird gar nicht ausgeführt werdenKANN weil 
sie bei 3 schon auf null gesetzet wird ist ja klar

aber wie soll ich es sonst machen ?! ich muss ja auch den kuren 
tastendruck feststellen können

außerdem wie kann man aus einem int. zurückkehren und gleichzeitig eine 
bestimmt funktion ausführen ?

die funktion soll ja nicht mehr im int. ausgeführt werden

von Schmittchen (Gast)


Lesenswert?

Erledige nicht zuviel in der Interruptroutine, setze hier nur 
Merker/Flags, die du dann in main() auswertest.

> ich muss ja auch den kuren tastendruck feststellen können
Was ist der Unterschied zwischen langem und kurzem Tastendruck? Richtig, 
beim kurzen Tastendruck wird die Taste früher losgelassen. Du mußt also 
das Loslassen auch noch auswerten, um zwischen kurz und lang zu 
unterscheiden.

Schmittchen.

von lordchen (Gast)


Lesenswert?

aber wie ??

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.