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.
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.
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
@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
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
@ 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
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
@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
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
@ 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
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
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
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
@ 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
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
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
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?
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