www.mikrocontroller.net

Forum: Codesammlung Universelle Tastenabfrage

Autor: peter dannegger (Gast)
Datum: 26.02.2006 22:10
Dateianhang: C_TAST.C (3,3 KB, 2672 Downloads) | formatierter Code

Unter "Tasten entprellen - Bulletproof" ist eine zuverlässige
Entprellung und gedrückt Erkennung für 1 .. 8 Tasten beschrieben.

Aber oftmals will man Tasten sparen, indem man unterschiedliche
Aktionen bei kurzem oder langem Drücken ausführt.

Außerdem ist eine Wiederholfunktion z.B. bei Eingabe von Werten
wünschenswert.

All das kann man mit wenigen weiteren Kodezeilen erreichen.

Im Interrupthandler wird eine Variable runtergezählt, sobald eine für
die Wiederholerkennung vorgesehene Taste gedrückt wurde. Nach der
Startzeit bzw. Wiederholzeit wird dann das Tastenbit in der Variable
key_rpt gesetzt. Die Startzeit und Wiederholzeit können unterschiedlich
gewählt werden.
Um nun einen Stellwert hochzuzählen, wird einfach die Funktion
get_key_rpt() aufgerufen, die dann das Tastenbit in key_rpt abfragt und
zurücksetzt. Damit zwischen Abfragen und Zurücksetzen kein
Timerinterrupt reinhaut, muß beides unter Interruptsperre erfolgen.

Die nächste neue Funktion ist get_key_short() für die Erkennung des
kurz Drückens. Das kann aber erst nach dem Loslassen erkannt werden.
Dazu wird der key_state ausgewertet, d.h. erst wenn dort das Tastenbit
wieder 0 ist, wird get_key_press() ein Wert übergeben, und kann
ausgeführt werden. Damit dazwischen kein Timerinterrupt erfolgt, muß
vor der Abfrage von key_state der Interrupt gesperrt werden,
get_key_press() enabled dann wieder die Interrupts.
Wird nur get_key_short() aufgerufen, d.h. nicht mit get_key_long() im
Wechsel, dann liefert es auch einen Wert zurück nach langem Drücken.

get_key_long() wiederum liefert erst dann einen Wert, wenn beide
Funktionen get_key_rpt() und get_key_press() das Tastenbit gesetzt
haben.

Anbei ein Programmbeispiel für alle 4 Funktionen.


Peter
Autor: Fabian (Gast)
Datum: 27.02.2006 11:12

Hallo,

Klasse! Ich benutze deine "normale" Entprellroutine schon ne
Weile...funktioniert einwandfrei. Die neue Funktionalität ist das
einzige was ich bisher vermisst hab...
Nur nochmal ne Frage dazu:

die Zeile
TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);  // preload for 10ms
tut was genau?
Wäre klasse wenn du die etwas "aufschlüsseln" könntest.

Gruß
Fabian
Autor: peter dannegger (Gast)
Datum: 27.02.2006 14:57

@Fabian

"die Zeile
TCNT0 = (u8)(s16)-(XTAL / 1024 * 10e-3 + 0.5);  // preload for 10ms
tut was genau?"


Nun T0 hat ja kein Compareregister.
Um ihn zu verkürzen, muß man ihn in jedem Interrupt neu laden.
Ein Laden mit -9 bedeutet, daß der nächste Interrupt nach 9
Zählschritten erfolgt.

XTAL ist die Quarzfrequenz (z.B. 1MHz)
1024 ist der Vorteiler
10e-3 = 10ms
+0.5 rundet
(s16) convertiert den float-Wert nach integer.
(u8) schneidet das High-Byte ab, da TCNT0 ja nur 8-bittig ist.


Peter
Autor: Fabian (Gast)
Datum: 27.02.2006 16:04

Alles klar...der erste Overflow passiert aber ganz normal nach 255ms
oder? also 1Mhz/1024 * 255 ... erst beim ersten overflow stellste ja
auf 10ms "um".

Richtig verstanden?

Gruß
Fabian
Autor: Micha (Gast)
Datum: 28.02.2006 14:30

Hallo Peter,

möcht nen FIFO anlegen, um Tastendrücke auch dann nicht zu verlieren,
wenn die Anwendung mit einer anderen Funktion bissel länger beschäftigt
ist.

Im Timer0-INT könnte ich dazu doch auch gleich die Bodys der
get_key_xx()-Funktionen unterbringen, die so erweitert werden, daß sie
ins FIFO schreiben können und cli() / sei() weglassen oder ist das
schlechtes Design??? cli() / sei() dann natürlich in der Funktion, die
den FIFO ausliest wegen der FIFO-"head" u. "tail"-indizies, die
sonst fehlerhaft werden könnten.

THX Micha
Autor: peter dannegger (Gast)
Datum: 28.02.2006 22:19

Ne FIFO würde ich aber nur für die einfache Druckerkennung machen.

Bei lang/kurz/wiederholung braucht man unbedingt ein direktes Feedback,
es sei denn, man ist Morsefunker.


Peter
Autor: andre (Gast)
Datum: 11.03.2006 11:59

Hallo,

ich blick nicht ganz durch den Code durch... Wie muss ich vorgehen,
wenn ich mit einem Taster bei kurzem und langem (ca. 1 sek) zwei
verschiedene Aktionen durchführen möchte?

andre
Autor: Peter Dannegger (peda)
Datum: 11.03.2006 12:18

@andre

"Wie muss ich vorgehen, wenn ich mit einem Taster bei kurzem und
langem (ca. 1 sek) zwei verschiedene Aktionen durchführen möchte?"

short = kurz
long = lang
//
      // release after short press: task 1
      // long press: task 2

    if( get_key_short( 1<<KEY1 ))
      LED_PORT ^= 1<<LED1;

    if( get_key_long( 1<<KEY1 ))
      LED_PORT ^= 1<<LED2;


Peter
Autor: andre (Gast)
Datum: 11.03.2006 12:27

Ich hab es so geändert:

#define REPEAT_MASK  (1<<KEY0)
#define REPEAT_START  100
#define REPEAT_NEXT  20


....

if( get_key_long( 1<<KEY0 ))
      value+=10;

 if( get_key_short( 1<<KEY0 ))
      value++;


Aber value wird immer 10 hochgezählt!
Autor: andre (Gast)
Datum: 11.03.2006 12:35

Hab den Fehler gefunden... der Vorteiler vom Teiler war falsch
eingestellt...

Allerdings muss ich mehr als 2,5 Sekunden einstellen... da muss wohl
ein 16 bit int her.
Autor: Karl Kalchgruber (Gast)
Datum: 16.03.2006 12:00

Hallo Peter,
ich hätte mal eine Frage zu deinem Code.
Wieso muß das lesen und zurücksetzen der Bits 'atomic' ausgeführt
werden? (z.B.: in Routine 'get_key_press')
Kommt das von der AVR-Architektur? (kenne diese nicht!)

/Koarl
Autor: Peter Dannegger (peda)
Datum: 16.03.2006 15:57

atomic meint, nicht durch Interrupts unterbrechbar und das bewirkt man
mit der Klammerung durch cli() + sei().

Nur C-Instruktionen, die in eine einzige Assemblerinstruktion übersetzt
werden, sind von Haus aus atomic (nicht teilbar).


Peter
Autor: Karl Kalchgruber (Gast)
Datum: 17.03.2006 10:50

Hallo,
mir ist schon klar was mit atomic gemeint. Was ich mich frage was würde
schief gehen wenn ich das 'atomic' weglasse.

z.B.: so

  key_mask &= key_press;                        // read key(s)
  key_press ^= key_mask;                        // clear key(s)

Meiner Meinung nach kann da falls ein Interrupt dazwischen kommt
nichts schief gehen. Da im Interrupt in der Variable 'key_press' nur
Bit gesetzt werden. (Oder ist auf dem AVR der 'AND' bzw. 'EXOR'
Befehl
nicht 'atomic')

/Koarl
Autor: peter dannegger (Gast)
Datum: 17.03.2006 11:24

key_press ^= key_mask;


Diese Instruktion besteht aus 3 Befehlen, ist also nicht atomar.

Wenn also genau zwischen lesen, exoren und zurückschreiben von
key_press der Timerinterrupt eine Taste erkennt, geht diese verloren.


Peter
Autor: Nils Hoffmann (Gast)
Datum: 20.04.2006 19:30
Dateianhang: Text1.c (3,6 KB, 393 Downloads) | formatierter Code

Hi,

ich habe heute den ganzen Tag damit verbracht (zu versuchen) den code
zu verstehen .... leider nur mit teilerfolgen ;) vielleicht kann mir
einer von euch weiter helfen.

Was mir am meisten Kopfschmerzen bereitet sind diese Shiftoperantionen
wie z.B.
#define REPEAT_MASK  (1<<KEY1^1<<KEY2)

auch dies hantieren mit den KEYs versteh ich nicht so ganz ... spricht
man damit einzelne Bits an oder sind das einfach Konstanten?
Falls es Konstanten sind warum macht man dann soetwas ?
if( get_key_long( 1<<KEY1 ))

könnte man da nicht einfach
if( get_key_long( 3 ))



Mit
#define KEY_PIN    PINB
werden doch die ganzen 8 Bit mit KEY_PIN verknüpft oder ? Dann müsste
es doch auch funktionieren wenn ich nur ein Bit des Ports mit KEY_PIN
verknüpfe oder nicht ? Folgendes ich habe einen Drehimpusgeber an
meinen Port0 (Atmel 8052)angeschlossen. Dieser hat 3 Adern ... 2 zur
Ermittlung der Drehrichtung und eine für den Drucktaster. Das Auswerten
des Drehimpulses habe ich mit Hilfe aus diesem Forum schon hinbekommen.
Vielen Dank nochmal !

*ich schweife schon wieder ab ;)*

Also Der Drehimpulsgeber ist folgendermaßen angeschlossen

P0^0 und P0^1 für die Drehrichtung
und
P0^2 für den Drucktaster

Deswegen möchte ich auch nur dieses Bit abfragen und mit der
Entprellroutine auswerten ... also habe ich
#define KEY_PIN    PINB
einfach durch
sbit KEY_PIN = P0^2;
ersetzt.


Die Tastenerkennung funktioniert jetzt auch, aber die Auswertung ob
lang oder kurz gedrückt worden ist leider nicht ....

Ich Programmiere in Keil und bin neu in der MC-Welt ... vielleicht kann
mir ja einer von euch etwas auf die Sprünge helfen?
Autor: Nils Hoffmann (Gast)
Datum: 20.04.2006 19:34

Hm

der Beitrag war eigentlich noch nicht fertig ... bin versehentlich auf
"submit" gekommen ! Leider kann man seine eigenen Beiträge nicht
nachträglich Editieren ... jedenfalls hab ich nicht gefunden wo ...
Naja ich hoffe man versteht ihn !

Ich habe die KEIL version des Entprellcodes nochmal angehängt
vielleicht hab ich ja da schon einen Fehler drin....

MfG
Nils
Autor: peter dannegger (Gast)
Datum: 20.04.2006 21:17

@Nils,

der Code ist so geschrieben, daß immer ein ganzer Port entprellt wird.

Welche der Portpins einen nun aber wirklich interessieren, übergibt man
den Abfragefunktionen als Bitmaske, die der Compiler aus der Bitnummer
per (1<<Bitnummer) erzeugt.

In meinem Beispiel werden 3 Pins abgefragt (key0..key2).


Peter
Autor: Nils Hoffmann (Gast)
Datum: 20.04.2006 21:26

Hi,

Ich bin immer wieder überrascht wie schnell man in diesem Forum Antwort
bekommt ! Daumen hoch !! g


vielen Dank

MfG
Nils
Autor: duundich (Gast)
Datum: 17.08.2006 21:25

Wiederholung nach langem Tastendruck:
if( get_key_long( 1<<BUTTON ) || get_key_rpt( 1<<BUTTON ))

Fehlt noch die Erkennung von gleichzeitig gedrückten Tasten! Falls da
jemand ne Idee hat, ich krieg's nicht hin..
Autor: Peter Dannegger (peda)
Datum: 18.08.2006 08:58

@duundich

Meinst Du ne Shift-Taste ?
if( get_key_press( 1<<KEY1 ){
  if( key_state & (1<<SHIFT_KEY) ){
// do action Shift + KEY1
  }else{
// do action KEY1
  }
}


Peter
Autor: duundich (Gast)
Datum: 18.08.2006 10:27

Ich fürchte nicht, da in diesem Fall der 'shift key' eine normale
Funktion hat: ich habe zwei Tasten, die jeweils bereits auf kurzen, und
langen||rpt Tastendruck geprüft werden, etwa so:
if( get_key_short( 1<<BUTTONA ))

programm -

if( get_key_short( 1<<BUTTONB ))

programm +

if( get_key_long( 1<<BUTTONA ) || get_key_rpt( 1<<BUTTONA ))

leiser

if( get_key_long( 1<<BUTTONB ) || get_key_rpt( 1<<BUTTONB )) 

lauter


Jetzt hätte ich gerne noch die Prüfung auf gleichzeitigen Tastendruck,
kurz oder lang (funktion: aus).
D.h., der Zustand müsste vor (oder/und nach) der Schwellzeit erkannt
werden, ohne, daß die anderen Prüfungen eingreifen. Das habe ich leider
nicht hinbekommen.

A        xxxxxxxxxxxxxx
B            xxxxxxxxxxxxxxxxx
T->                              |


Würde mich über einen Hinweis in die richtige Richtung sehr freuen!
Autor: noXe (Gast)
Datum: 30.08.2006 18:16

Hi,

also ich habe so eben versucht den Code vom peter dannegger an einem
mega8 auszuprobieren. Habe den PORTA durch PORTD ersetz und die XTAL
auf 16Mhz eingestellt....bekomme aber nichts sinnvolles raus. Die drei
LEDs läuchtet permanent und das wars.

Ne Idee was ich falsch gemacht haben könnte?
Autor: Pete (Gast)
Datum: 09.09.2006 09:07

Versuch es mal mit 1 Mhz.
Autor: Peter Dannegger (peda)
Datum: 09.09.2006 17:57

@noXe

"Ne Idee was ich falsch gemacht haben könnte?"


Tja, was soll man dazu sagen ?

Wenn wenigstens die komplette Source als Anhang dabei wäre, dann könnte
man schonmal Softwarefehler suchen. Aber hellsehen kann ich leider
nicht.

Und so ins Blaue: "Versuch es mal mit 1 Mhz." bringt meistens
nichts.


Peter
Autor: André (Gast)
Datum: 21.10.2006 19:13

Danke an Peter für den Quelltext samt ausführlicher Kommentierung.
Hab erstmal ein bisschen Anlauf gebraucht um das Programm richtig zu
deuten, da jeder einen etwas anderen Programmierstil hat.
Hab es auf meine Bedürfnisse angepasst und es funktioniert wunderbar.

Besten Dank nochmal dafür.
Autor: dagobert (Gast)
Datum: 20.04.2007 12:06

Hallo!

Bei dem von Peter realisierten Code ist ein konstanter Tastendruck
(long) nicht wirklich möglich, oder sehe ich das falsch?
Bei längerem Drücken reagiert das System wie bei kurzem Tastendruck.
Lediglich bei schnellem aufeinanderfolgenem Tastendruck kann eine
Änderung (der Routine) festgestellt werden.
Ist dem so, oder habe ich etwas falsch gemacht?

Danke für Eure Hilfe
Autor: Jörg Bayer (senner05)
Datum: 19.06.2007 22:49

Hallo zusammen,

ich hab nochmal eine Frage zum deaktivieren der Interrups.

Folgendes:
Ich hab den Code "missbraucht" um eine Tastenabfrage über RS232 zu
realisieren. Das sieht im Prinzip so aus:
Jedesmal wenn eine Taste gedrückt wird (oder losgelassen) wird der
keystate in einem byte gesendet.
Jedes Bit steht dabei für eine Taste.
Dieses Byte wird dann einfach für den "ursprünglichen" Tastenport
verwendet!

Ich weiss, dass das garantiert auch eleganter gelöst werden kann aber
mir gefällt es da ich dann auch ohne weiteres die zusätzlichen
Tastenfunktionen nutzen kann (außerdem bin ich ein absoluter
Programier-Anfänger so dass ich froh bin wenn es für etwas schon eine
fertige Lösung gibt ;-)) - und es funktioniert soweit!

Das Problem das ich jetzt seh ist, wenn die Interrups deaktiviert sind
kann ja auch kein neuer keystate empfangen werden - wie wahrscheinlich
das ganze ist sein mal dahingestellt (der keystate wird zuerst bei einem
receive-interrupt in einen Buffer geschrieben...) aber es ist nunmal
Möglich!

Deshalb nochmal die Frage (ich habs oben nicht ganz verstanden):
Warum verlier ich den Tastendruck (nehmen wir mal an, dass die Tasten an
einem Port sind)?
Und kann ich z.B. einfach alle Interrups außer dem
UART-Receive-Interrupt deaktivieren? Ich mein das sind doch ganz andere
Zeitdimensionen (empfangen -> in Buffer schreiben -> Buffer
auswerten)...

Ich hoffe ihr könnt mir weiterhelfen

Gruß
Jörg
Autor: (geloescht) (Gast)
Datum: 29.06.2007 20:53

(Dieser Beitrag wurde geloescht)
Autor: Markus (Gast)
Datum: 16.07.2007 16:04

Hallo!

Ich versuche die Entprellroutine zu verwenden.
Leider hab ichs noch nicht ganz geschafft.

Ich hab einen ATTiny26 und versuche folgendes zu realisieren:

3 LEDs an PORTA 1,3,4
1 Taster an PINA 7

Das Programm soll wie folgt funktionieren:

- beim einschalten, alle LEDs aus.
- bei jedem kurzen tastendruck die nächste LED einschalten und bei der
letzten bleiben bis....
- bei langem Tastendruck wieder auf 0 gesetzt wird.

Ich hoffe das war verständlich.

Dazu sind doch die Funktionen short und long oder?
mit der Funktion get_key_press funktioniert das raufzählen, aber wie
realisiere ich den langen tastendruck mit dem rücksetzen?

Ich hoffe mir kann da wer helfen.
Autor: Peter Dannegger (peda)
Datum: 16.07.2007 18:10

Markus wrote:

> Dazu sind doch die Funktionen short und long oder?

Genau.
Siehe Beispiel.
Nicht vergessen, die Taste in REPEAT_MASK einzutragen.


Peter
Autor: Markus (Gast)
Datum: 17.07.2007 08:02
Dateianhang: file.c (5,6 KB, 400 Downloads) | formatierter Code

Ich wollte eigentlich die Datei anhängen, hat aber scheinbar nicht
geklappt.

Zum Problem:
Bei kurzem Tastendruck leuchtet die erste LED, danach geht sie gleich
wieder aus.
Drücke ich mehrmals hintereinander funktioniert es auch. Sobald ich aber
nicht mehr drücke gehen alle LEDs wieder aus.(sollte eigentlich erst bei
key_press_long sein)

Also kann was an dieser Routine nicht stimmen.
Kann es sein, dass er da probleme hat, weil auch die LEDs am selben PORT
liegen?

mfg markus
Autor: Markus (Gast)
Datum: 17.07.2007 08:25

Hab den Fehler gefunden.

Es lag daran, dass in dieser Routine die Taster aktive low sind. Meiner
ist jedoch aktvie high.

Habe folgende Zeile geändert:
i = key_state ^ ~KEY_PIN; ->  i = key_state ^ KEY_PIN;

Das war hoffentlich richtig. Zumindest funktioniert es jetzt :)
Autor: Thomas Kühne (tommes)
Datum: 30.08.2007 20:19

Hallo Peter,
ich habe mich gerade mit deinem Code beschäftigt.
Ich glaube ich habe dabei nen Fehler gefunden:
und zwar einen allgemeinen Fehler bei der Behandlung von lange
gedrückten Tasten. Wenn ich deine Routine in der ISR richtig verstehe,
dann setzt du die rpt Zählvariable immer wieder auf den Ausgangswert
solange keine Taste gedrückt wird. Sobald eine Taste gedrückt ist,
geschieht dies nicht mehr und die rpt wird heruntergezählt. Jedoch
unterscheidet deine Routine dann nicht welche Taste gedrückt ist und wie
lange bereits. Kann nicht im Moment der Fall eintretten, dass (Annahme
REPEAT_START = 50) Taste 1 die ersten 40 Interrupts gedrückt ist und
nach Interrupt 30 auch noch Taste 2 hinzukommt. Nun wird im Code nach 50
Interrupts bei Taste 2 ein langes drücken festgestellt, obwohl sie nur
20 Interrupts gedrückt war. Ich hoffe das ist so weit verständlich.
Und sollte auch nur als Anregung dienen.

Gruß Thomas
Autor: Peter Dannegger (peda)
Datum: 31.08.2007 12:43

@Thomas,

das ist absichtlich so.

In der Praxis ist es so, daß man nur eine Taste lange drückt, z.B. count
up und losläßt, wenn der gewünschte Wert erreicht ist.
Würde man gleichzeitig count down drücken, würde der Wert immer +1,-1
machen, was ja ziemlich sinnlos ist.


Damit man eine Shift-Taste definieren kann (z.B. count +1, oder +10),
gibt es die Maske mit der nur die Repeat-Tasten definiert werden.

Zu entprellende Eingänge ohne Repeat können also gleichzeitig aktiv sein
(z.B. Endlagenschalter).


Peter
Autor: Markus _neu (markush)
Datum: 20.09.2007 22:52

Hi Leutz,

ich versuche grad die Routine auf einem Mega32 mit 16MHz Takt zu
benutzen. Ich hab das Original C-Beispiel aus der Artikelsammlung
benutzt (http://www.mikrocontroller.net/articles/Entprellung). Zur
Auswertung geb ich einen Text auf ein LCD aus:
    if( get_key_press( 1<<KEY0 )) {
      lcd_gotoxy(0,1);
      lcd_puts("T0");            
                    }
    if( get_key_press( 1<<KEY1 )) {
      lcd_gotoxy(0,1);
      lcd_puts("T1");            
                    }

    if( get_key_press( 1<<KEY2 )) {
      lcd_gotoxy(0,1);
      lcd_puts("T2");            
                    }


Soweit funktioniert das auch, nur zeigt bei mit der erste Taster T0 oft
fälschlicherweise T1 an. Und zwar immer wenn vorher eine andere Taste
gedrückt war. Ich hab schon die verschiedensten Sachen probiert, weiss
mir aber mittlerweile nicht mehr weiter. Any hints?

Markus
Autor: Peter Dannegger (peda)
Datum: 21.09.2007 15:08

Markus _neu wrote:

> Soweit funktioniert das auch, nur zeigt bei mit der erste Taster T0 oft
> fälschlicherweise T1 an. Und zwar immer wenn vorher eine andere Taste
> gedrückt war. Ich hab schon die verschiedensten Sachen probiert, weiss
> mir aber mittlerweile nicht mehr weiter. Any hints?

Wackler, Kurzschluß, unterbrochene Pullups, ...


Schreib mal die LCD-Texte hintereinander, dann sieht mans besser.

So weißt Du ja nicht, ob ein Text von einem anderen überschrieben wurde
und wie oft er geschrieben wird.


Peter
Autor: Markus _neu (markush)
Datum: 21.09.2007 15:43

Peter Dannegger wrote:
>
>
> Schreib mal die LCD-Texte hintereinander, dann sieht mans besser.
>
> So weißt Du ja nicht, ob ein Text von einem anderen überschrieben wurde
> und wie oft er geschrieben wird.
>
>
> Peter

Ja, gute Idee. Werd ich heute abend gleich mal probieren.

Markus
Autor: Markus _neu (markush)
Datum: 21.09.2007 21:19

Hi,

danke für deine Tipps Peter. Das Problem waren nicht aktivierte interne
Pullups !?!

Hab ich völlig übersehen. Durch das hinternander schreiben der Ausgabe
konnte ich sehen dass da tatsächlich teilweise mehrere Tasterdrücke auf
einmal registriert wurden.

Gruß - Markus
Autor: mgiaco (Gast)
Datum: 27.09.2007 10:23

Was machen wenn man 10 Tasten braucht?
8 Stück funktionieren wunderbar.

danke
mathias
Autor: Falk Brunner (falk)
Datum: 27.09.2007 11:06

@ mgiaco (Gast)

>Was machen wenn man 10 Tasten braucht?

Da wird man wohl oder übel den Code anpassen müssen und auf zwei Ports
zugreifen müssen. Oder gleich ne Matrix aufbauen, ist auch in der
Codesamlung verfügbar.

MFG
Falk
Autor: ben (Gast)
Datum: 06.05.2008 14:36

hallo,
fang grad erst an und bräuchte nur ne ganz normale
interrupt-tastenentprellung für einen taster.

würde mich über eine antwort sehr freuen.
ich hab nen AT90CAN64 grade dran...

gruß,

ben
Autor: Sebastian (Gast)
Datum: 13.05.2008 22:45

Hallo,

ich probier grade Peters C-Komfortroutine aus:
http://www.mikrocontroller.net/articles/Entprellun...

Mit WinAVR-20080430 funktioniert diese bei mir allerdings nur nach
Einfügen einiger "volatile":
volatile uint8_t key_state;    // debounced and inverted key state:
                                  // bit = 1: key pressed
volatile uint8_t key_press;       // key press detect
 
volatile uint8_t key_rpt;         // key long press and repeat

Anderer Punkt: Der letzte Code-Abschnitt in dem Beispiel soll wohl den
Status der unteren drei LEDs erhalten und das Leuchten einer weiteren
LED über die höheren fünf LEDs schieben:
if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){
      uint8_t i = LED_PORT;
 
      i = (i & 0x07) | ((i << 1) & 0xF0);
      if( i < 0xF0 )
        i |= 0x08;
      LED_PORT = i;
Dieser Teil geht bei mir im Simulator mit AVR-Studio 4.14 (auch
anschaulich mit hapsim) sehr gut. In der Realität passiert beim Drücken
von KEY2 allerdings nichts.
Ich habe LED_PORT PORTB und KEY_PORT PORTD, also die Standardschaltung
aus dem ASM-Tutorial. Ins Blaue vermutet könnte das daran liegen, das
mein Quarzoszillator mit an PortB hängt. Folgendes funktioniert nämlich
(einfaches an/aus der vierten oder Blinken durch
Wiederholungserkennung):
if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){
    
  LED_PORT ^=0x08;

Viele Grüße & gn8 !
Sebastian
Autor: Sebastian (Gast)
Datum: 15.05.2008 10:59

Wenn 's da sonst keine Meinung zu gibt werde ich den Entprellung-Artikel
mal entsprechend anpassen.
Grüße,
Sebastian
Autor: Charly Grosse (student)
Datum: 15.05.2008 23:29

Falk Brunner wrote:
> @ mgiaco (Gast)
>
>>Was machen wenn man 10 Tasten braucht?
>
> Da wird man wohl oder übel den Code anpassen müssen und auf zwei Ports
> zugreifen müssen. Oder gleich ne Matrix aufbauen, ist auch in der
> Codesamlung verfügbar.
>
> MFG
> Falk

Hallo,

drei!!! Ports (einer für Matrix, zwei für je 8 Tasten) würde mich auch
(in gleichzeitiger Interrupt Abfrage!!!) interessieren. Habe leider
nichts hierzu gefunden - liegt das an mir - gibt es so etwas schon ?

Habe versucht Peter's Beispiel dahingehend zu erweitern ... aber
anscheinend funzt meine Erweiterung manchmal nicht, an anderen Tagen
problemlos ....!

Würde mich daher lieber auf professionellen Code verlassen!

Peter, hast Du vielleicht einen Hinweis, wie man so etwas professionell
implementiert ? Wie würdest Du Deine Routine erweitern ? Matrix an sich
ist kein Problem. Problem ist der Portwechsel ... Tasten verschiedener
Ports im Wechsel ....!!!!

Vielen Dank im voraus,

Grüsse

Antwort schreiben

Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel





Hinweis: der Originalbeitrag ist mehr als 6 Monate alt.

webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net