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
Schon mal in der Codesammlung nachgesehen ? Z.B.: http://www.mikrocontroller.net/forum/read-4-20549.html Peter
@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
Thema Stackpointer: Der Prozessorkern kann ja nicht wissen, wie viel RAM angeschlossen ist. Wohin zeigt der SP beim 8051 nach dem Reset?
@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
OK Peter dann werde ich es mal audprobieren. Ansonsten müßte der geschriebene Code funktionieren so wie ich ihn geschrieben habe oder?? Julien
Hi! Wenn es möglich ist schalte doch standardmäßig nach GND(wie STK), dann kannst du uC-interne PullUp's verwenden. MFG Uwe
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.