Tasten entprellen

Gast #30365
Lesenswert?

Hallo zusammen,

Ich habe folgendes Problem:

Ich möchte 3 Taster entprellen.
Je nachdem welcher Taster gerade gedrückt wird soll eine Aktion 
ausgeführt werden. In meinem Fall jeweils unterschiedliche Zahlen 
angezeigt werden.

Ich habe den Code gepostet, leider funktioniert es irgendwie nicht .

Kann mir irgendjemand sagen woran dies liegt??
Oder Welche möglichkeit gibt es?

Danke im Vorraus.
Angehängte Dateien:
Gast #30366
Lesenswert?

Also...
da hier noch keine Antwort steht. Ich will's mal versuchen.
Hier einfach dreiste Kommentare:
1. Wieso benutzt Du den Timer nur als For-Schleifen-Ersatz?
- Du kannst doch einfach "Busy-Waiting" machen.
2. Du verUNDest mit Taster-Old, aber das Register wird nirgends gesetzt?

Mein Vorschlag zum Entprellen mit Timer-Routine und in schön:
In der Timeroutine die Tasten prüfen und dann einen Zähler hochzählen, 
falls gedrückt. Anderenfalls Zähler auf 0 zurücksetzen. Bei Überlauf ein 
Statusflag für das Hauptprogramm setzen - Von diesem Zurücksetzen 
lassen, falls die Aufgabe bearbeitet wurde. Die Timerkonstante kannst Du 
dann so setzen, daß er ordentlich entprellt, aber Dir noch keine große 
CPU-Zeit vom Hauptprogramm wegschluckt.
Oder auch in Hardware:
RC-Kombination. Du machst einfach einen Tiefpaßfilter an Deine Taste 
dran, dann kommt das Prellen nicht mehr rüber.
Gast #30367
Lesenswert?

Danke Onno für den Tipp,

Ich habe jetzt einmal versucht deinen Tipp umzusetzten.
Allerdings hat mein Code nicht so funktioniert.

Vielleicht kann jemand sich den neu geposteten Code noch einmal 
anschauen und mögliche Fehler mir mitteilen.

Oder hat mir jemand zu meinem Problem einen funktionsfähigen Code.


Vielen dank im Vorraus
Angehängte Dateien:
Gast #30369
Lesenswert?

@Peter

dieser Code ist gut gemeint, nur leider funktioniert er nicht.
Ich habe ihn 1 zu 1 übernommen um ihn zu testen.

Die einzigste Änderung ist der DEVICE, da ich einen 8515 verwende.

Hast du eine Idee woran dies liegen könnte.
Ach ja ich benütze das STK500 und AVR Studio 4


Julien
Gast #30371
Lesenswert?

@ Peter

Vielen Dank, es funktioniert.

Allerdings habe ich jetzt noch ein paar Fragen.

Hab ich es richtig verstanden, dass in Register key_press die aktuell 
gedrückten Taster angezeigt werden?

In deinem Code wird ja ein kompletter PORT eingelesen.
Wenn jetzt beispielsweise nur Bit0 bis Bit3 des Key_port für die Taster 
verantwortlich sind und die restliche 4 als Ausgang definiert sind, 
funktioniert der Code dann immer noch?

Oder was ist zu ändern?

Danke Julien
#30372
Lesenswert?

Ja, der Code funktioniert von 1 bis 8 Tasten.
Du hast quasi 8 völlig separate Entprellschaltungen.
Du must einfach nur die Bits auswerten, an denen auch eine Taste ist, 
die anderen Bits ignorierst Du.

Jedes gesetzte Bit in key_press bedeutet, das die dazugehörige Taste 
seit dem letzten Löschen von key_press von losgelassen nach gedrückt 
gewechselt hat und das diese beiden Zustände mindestens 4 
Timerinterrupts hintereinander stabil anlagen.


Peter
#30374
Lesenswert?

@Andreas,

der ATTINY13 soll ja 64 Byte SRAM haben. Dann wäre z.B. ein Resetwert 
für den SP von IO-Bereich + 64 Byte für alle AVRs sinnvoll.
Der genaue Wert ist ja nicht wichtig, er sollte eben nur auf einen 
gültigen Bereich zeigen.


Insbesondere für die armen Wichte, die sich teuer irgendeine Software 
haben schreiben lassen z.B. für den AT90S1200, der ja nun abgekündigt 
wird und die nur ein Hex-File haben, wäre es super, wenn der neue 
ATTINY2313 dann den Stack schon auf eine gültige Adresse setzen würde.



Beim 8051 wird der Stack hinter die 1.Registerbank gesetzt.

Der Einsatz der weiteren Registerbänke erfolgt meistens nur in 
Interrupts, d.h. bis dahin hat man dann schon genügend 
Programmierkenntnisse, um den Stack woanders hin zu setzen.


Peter
Admin Persönliche Seite #30375
Lesenswert?

Ein Setzten des SP auf den kleinsten gemeinsamen Nenner finde ich nicht 
sehr sinnvoll, das verleitet nur zur Faulheit.

Außerdem bezweifle dass der Fall mit dem AT90S1200 und dem hex-File so 
häufig ist, und das hex-File kann man ja dank der relativen Sprünge 
ziemlich einfach für die Stack-Initialisierung anpassen...

Naja, so eine Kleinigkeit ist wohl einfach Geschmackssache und 
eigentlich keine Diskussion wert.

Andreas
Gast #30376
Lesenswert?

@ Peter

ich bins nochmal.

ich habe versucht anstelle einer LED eine 7 Segment anzeige anzusteuern.
Leider funktioniert es nicht ganz so wie ich es mir vorstelle.
Wenn z.B. Taster1 wieder losgelassen wird soll eine 1 angezeigt werden 
und erst wenn ein anderer Taster betätigt wird, ädert sich die Anzeige.

Hier der geäderte Code.

MAIN:
  CLI
  CBR key_press, 1  ;Bit0 in key_press löschen
  CBR key_press, 2  ;Bit1 in key_press löschen
  CBR key_press, 4  ;Bit2 in key_press löschen
  CBR key_press, 8  ;Bit3 in key_press löschen
  CBR key_press, 128  ;Bit7 in key_press löschen
  BST key_press, 4        ;Bit4 in T-Flag kopieren
  BRTS ST100_1          ;Ziffer 1 anzeigen
  BST key_press, 5  ;Bit5 in T-Flag kopieren
  BRTS ST100_2    ;Ziffer 1 anzeigen
  BST key_press, 6  ;Bit6 in T-Flag kopieren
  BRTS ST100_3    ;Ziffer 1 anzeigen
  CLR  key_press  ;clear, if key press action
                                ;done
  SEI

RJMP  MAIN

so sehen die Unterprogramme aus:

ST100_0:        ;Ziffer 0

  CBI PORTB, PB3      ;A  auf 0 setzen
  CBI PORTB, PB0      ;B  auf 0 setzen
  CBI PORTB, PB1      ;C  auf 0 setzen
  CBI PORTB, PB2      ;D  auf 0 setzen

RET

Wo ist der logische Fehler?

Julien
Gast #30377
Lesenswert?

Hallo zusammen,

wie oben schon beschrieben habe ich ein Problem mit der Anzeige.

Ich habe jetzt einmal den gesamten Code gepostet, damit Ihr einen 
Gesamteindruck bekommt.
Nachdem ich den Code in den AVR überspielt habehatte ich folgendes 
Ergebnis:
-> nach dem RESET zählt meine Anzeige von 1 bis 3 ununterbrochen durch
-> Die betätigung der Taster hat keinen Einfluß

Da ich die Entprellerschaltung GET8KEY verwendet habe wollte ich auf 
dieser aufbauen.

Laut meiner Logik sollte es funktionieren!

Könntet Ihr euch mal den Code anschauen und mir sagen wo mein fehler 
liegt.

Danke im Vorraus
Angehängte Dateien:
Gast #30378
Lesenswert?

Hi!
Verpasse mal deinen Eingängen PullUp's, die hat der Herr Dannegger 
leider vergessen. Die Taster hängen dadurch in der Luft! (Einfach $70 
nach Portb ausgeben, am besten gleich am Anfang)

MFG Uwe
#30379
Lesenswert?

Da hat Uwe recht. Wenn man nicht das STK nimmt, muß man entweder externe 
Pull-Ups an die Tasten legen oder die internen aktivieren.


Aber Dein Fehler liegt woanders:

Du rufst Funktionen mit RCALL auf und gehst aber mit RJMP zurück.
Das geht immer in die Hose, Du darfst ausschließlich mit RET 
zurückgehen.


Allgemein solltest Du zwischen Funktionen nicht mit RJMP hin und 
herspringen. Dadurch entsteht dann nämlich der PIC übliche völlig 
unübersichtliche Code.
Die PICs haben nur einen sehr kleinen Stack und deshalb gehts da oft mit 
GOTO kreuz und quer, bis man den Faden verloren hat.


Bei den AVRs hast Du aber mehr als genug Stack, da kann man den Code 
schön modular schreiben, auch wenn RCALL und RET mehr Takte dauern.
Besser lesbarer Code und dadurch weniger Fehler machen das allemal wett.


Außer beim AT90S1200 hat R0 eine Sonderfunktion (LPM), daher solltest Du 
es nicht einem Interrupthandler exklusiv zuweisen.


Peter
Gast #30380
Lesenswert?

@ Peter und Uwe

Eure Tipps sind gut gemeint, nur leider habe ich jetzt keine 
Tast-funktion mehr, denn ohne pull Up's habe ich von 0 nach 1 geschaltet 
und mit pull Up's wäre das jetzt von 1 nach 1 und da ist logischer weise 
kein Tastendruck erkennbar.

Des weiteren hab ich RJMP verwendet da ich nach Ablauf einer Funktion 
nicht wieder an die Aussprung Stelle zurück kehren möchte.

Wie soll ich weiter vorgehen?

Danke

Julien
Gast #30381
Lesenswert?

Noch etwas, wenn ein Branch Befehl ausgeführt wird und ich nach Ablauf 
dieser Funktion wieder zu meiner Aussprungstelle gelangen will muss ich 
doch einen RJMP Befehl verwenden oder gibt es auch hier eine andere 
Möglichkeit?

Julien
#30382
Lesenswert?

Du kannst innerhalb einer Funktion hin- und herspringen, wie Du lustig 
bist, aber eben nicht in eine andere Funktion.

Man sollte aber der besseren Lesbarkeit wegen unnütze Sprünge vermeiden, 
d.h. das Programm so hinschreiben, wie es chronologisch auch ausgeführt 
wird.

Bei bedingten Sprüngen, die nur einen if-Zweig haben, dreht man die 
Bedingung um, d.h. man überspringt den if-Zweig, wenn die Bedingung 
nicht erfüllt ist.

Bei if-else-Bedingungen schreibt man beide Aktionen hintereinander und 
springt nach der 1. Aktion hinter das Ende der 2.Aktion:

brne mache2 ;Teste Bedingung
; hier mache die Sachen bei Gleichheit
rjmp ende2
mache2:
; hier mache die Sachen bei Ungleichheit
ende2:
; hier gehts in jedem Fall weiter


Ein guter Programmierstil ist, eine Funktion immer an der 1.Zeile 
aufzurufen und immer in der letzten Zeile mit dem einzigen RET in dieser 
Funktion zu verlassen.


Peter
Gast #30383
Lesenswert?

Vielen Dank Peter für deine Tipp.

Werde Ihn mir zu Herzen nehmen.

Aber was mache ich nun mit meinen Tastern die keine Tastfunktion mehr 
besitzen seit sie einen Pull Up besitzen?
Sollte ich hardwaremäßig von 1 nach 0 schalten so wie es das STK  tut 
oder was soll ich machen damit mein Code funktioniert?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren