mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Tasten entprellen


Autor: Julien (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Onno (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Julien (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal in der Codesammlung nachgesehen ?

Z.B.:

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


Peter

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1 zu 1 kannst auch nicht gehen:

Der 1200 hat einen Hardwarestack, beim 8515 mußt Du den Stack erst 
einrichten.

Im Gegensatz zum 8051 lassen die AVR-Entwickler den Stack nach einem 
Reset erstmal in den Wald zeigen. Warum, wissen die Götter.


Peter

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thema Stackpointer: Der Prozessorkern kann ja nicht wissen, wie viel RAM 
angeschlossen ist. Wohin zeigt der SP beim 8051 nach dem Reset?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julien (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Prinzip ist es egal, die Widerstände müssen nur den entgegengesetzten 
Pegel anlegen, wenn die Taste offen ist.

Der Code ist für 1->0 beim Drücken ausgelegt.
Diese Zeile macht das:

com irw0 ;low active

Peter

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK Peter

dann werde ich es mal audprobieren.

Ansonsten müßte der geschriebene Code funktionieren so wie ich ihn 
geschrieben habe oder??

Julien

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Wenn es möglich ist schalte doch standardmäßig nach GND(wie STK), dann 
kannst du uC-interne PullUp's verwenden.

MFG Uwe

Autor: Julien (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ihr beiden

Vielen Dank für alles ....

Es funktioniert jetzt

Gruß Julien

Antwort schreiben

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

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.