Grüße euch Ich hab ein kleine Frage zu meinem Programm. Es soll beim betätigen eines Tasters eine LED aufleuchten und beim erneuten betätigen des gleichen Tasters soll die LED wieder ausgehen. Bei meinem geschrieben Programm funktioniert dies aber nicht immer obwohl ich die LED betätige geht die LED nicht aus oder an. Kann mir mal einer helfen? .nolist .include "m8def.inc" .list ldi r16, 0x01 out DDRD,r16 sbi PORTD, PD7 rjmp main main: sbic PIND, PD7 rjmp main loop2: sbi PORTD, PD0 sbic PIND, PD7 rjmp loop2 cbi PORTD, PD0 rjmp main
marvin schrieb: > Grüße euch > > Ich hab ein kleine Frage zu meinem Programm. Es soll beim betätigen > eines Tasters eine LED aufleuchten und beim erneuten betätigen des > gleichen Tasters soll die LED wieder ausgehen. Bei meinem geschrieben > Programm funktioniert dies aber nicht immer obwohl ich die LED betätige > geht die LED nicht aus oder an. Ich denke nicht, dass du physisch in der Lage bist innerhalb weniger Mykro-Sekunden eine Taste zu drücken und wieder loszulassen. Denn genau solange braucht dein µC bis er das nächste mal überprüft ob du die Taste gedrückt hast. Einen einzelnen Tastendruck (im Gegensatz zur Frage "Ist die Taste gerade niedergedrückt?") einwandfrei und sauber zu erkennen ist erstaunlicherweise gar nicht so einfach. Es ist schwierig genug, dass diesem Themenkreis im Tutorial ein eigener Artikel gewidmet ist. Und der steht nicht am Anfang des Tutorials sondern schon mitten drinn, denn dazu müssen schon ein paar andere Techniken bekannt sein, wenn man es ordentlich machen will. AVR-Tutorial
"Ich denke nicht, dass du physisch in der Lage bist innerhalb weniger Mykro-Sekunden eine Taste zu drücken und wieder loszulassen. Denn genau solange braucht dein µC bis er das nächste mal überprüft ob du die Taste gedrückt hast." Kannst du es mir vielleicht genau erläutern?
marvin schrieb: > "Ich denke nicht, dass du physisch in der Lage bist innerhalb weniger > Mykro-Sekunden eine Taste zu drücken und wieder loszulassen. Denn genau > solange braucht dein µC bis er das nächste mal überprüft ob du die Taste > gedrückt hast." > > > Kannst du es mir vielleicht genau erläutern? Ganz einfach. Das hier ist ein Ausschnitt aus deinem Code
1 | ... |
2 | main: |
3 | |
4 | |
5 | sbic PIND, PD7 ; ******************* |
6 | rjmp main |
7 | |
8 | |
9 | loop2: |
10 | sbi PORTD, PD0 |
11 | |
12 | sbic PIND, PD7 ; ******************* |
13 | rjmp loop2 |
14 | ... |
mit dem ersten SBIC stellst du fest, dass die Taste gedrückt wurde. Wenn das der Fall ist, soll es bei LOOP2 weiter gehen. Du schaltest die LED ein und mit dem zweiten SBIC möchtest du gerne feststellen ob die Taste nochmal gedrückt wurde. Deine Annahme lautet hier: Zwischen den ersten SBIC und dem zweiten SBIC wurde die Taste wieder losgelassen! Aber: Über wieviel Zeit reden wir denn, die zwischen den ersten SBIC und dem zweiten vergeht? Das sind (je nach Taktfrequenz des µC) ein paar µs! Und in der Zeit schafft kein Mensch eine Taste zu drücken und wieder loszulassen. D.h. der zweite SBIC reagiert nicht darauf, dass die Taste erneut gedrückt wurde. Der reagiert darauf, dass die Taste immer noch gedrückt IST! Und als Folge davon wird eben nicht bei LOOP2 weiter gemacht, sondern der RJMP übersprungen, die LED ausgeschaltet und es geht bei MAIN weiter. Wo, nebenbei bemerkt, der dortige SBIC feststellen wird, dass die Taste immer noch gedrückt ist und damit sofort wieder zu LOOP2 geht, die LED wieder einschaltet, der darauf folgende SBIC feststellt, dass die Taste immer noch gedrückt ist, die LED wieder ausschaltet usw. usw. Aus Sicht deines µC ist alles was du tust wie eine Superzeitlupe. Was für dich schnell ist, ein Wimpernschlag, ist für deinen µC eine halbe Ewigkeit. Egal wie sehr du dich bemühst eine Taste möglichst kurz zu drücken und wieder loszulassen, dein µC arbeitet in dieser Zeit ein paar Zehntausend Befehle ab. Die Annahme, dass du es schaffst zwischen dem ersten SBIC und dem zweiten die Taste wieder loszulassen, so dass der zweite SBIC den nächsten Tastendruck erkennen kann, ist fehlerhaft. Denn das schaffst du aus Zeitgründen eben nicht.
Hmmm Könnte natürlich auch sein, dass dein Verständnis darüber, was du mit dem SBIC eigentlich machst, fehlerhaft ist. Damit stellst du nur den momentanen Zustand des Eingangspins fest. Da ist keine wie auch immer geartete Logik involviert, die den Vorgang des Niederdrückens feststellt. Es ist wie das kurzzeitige Reinschauen ins Badezimmer, ob das Licht brennt. 'Jawohl, brennt' oder 'Nein, brennt nicht'. Aber du hast damit keine Information, ob zwischen den Besuchen im Badezimmer jemand da war und das Licht ein oder ausgeschaltet hat.
danke für ratschläge ich hab ein neues programm geschrieben, zwar ist die Funktion des Programmes diesmal nicht ganz so schlimm wie beim ersten Programm, aber immer noch nicht perfekt:(. Kann man einen Taster überhaupt mit der Polling-Methode gescheit toogeln oder ist dies nur mit Interrupts perfekt möglich? .nolist .include "m8def.inc" .list ldi r16,0x01 out DDRD, r16 ldi r16, 0x00 out PORTD, r16 sbi PORTD,PD7 ; Pull-up Widerstand aktivieren ldi r16, 0x01 main: sbic PIND, PD7 rjmp main in r17,PORTD eor r17,r16 out PORTD, r17 rjmp main
aso sry ich habe natürlich meinen Taster nicht entprellt, ich wollt nur ein Feedback für mein Programm
marvin schrieb: > sry ich habe natürlich meinen Taster nicht entprellt Dein Programm würde Funktionieren, wenn du den Taster über Hardware entprellen würdest. Das Toggeln machst du richtig. Jetzt lies dir im Tut doch mal das mit dem entprellen durch, da gibt es auch glaub auch was ohne Interrupt.
Jürgen schrieb: > Dein Programm würde Funktionieren, wenn du den Taster über Hardware > entprellen würdest. Sorry, auch dann nicht. Du musst die Flanke (von high nach low) auswerten, ansonsten eort sich dein m8 zu tode solange du den Taster haltst.
>"Sorry, auch dann nicht. Du musst die Flanke (von high nach low) >auswerten, ansonsten eort sich dein m8 zu tode solange du den Taster >haltst." Das verstehe ich jetzt nicht
marvin schrieb: > sbic PIND, PD7 > rjmp main Solange du den Taster hältst, wird rjmp main übersprungen. Das sind in der Sekunde bei 1 MHz einige 10000 mal.
Probier mal mein Code für eine Taste aus. Das Beispiel ist für pinc1, aber as kannst du ja ändern. Hab das jetzt mal auf die schnelle aus einem Programm von mir herauskopiert. Braucht nur ein niederwertiges Register und ein Bit für die Flanke. Ausserdem Kannst du in der Main jederzeit mit tst Taste prüfen, ob die Taste noch gehalten wird, oder losgelassen wurde.
1 | .def taste = r1 |
2 | .def s = r5 ;S-Register |
3 | .def temp1 = r16 ;Trash |
4 | .def flags = r24 |
5 | |
6 | |
7 | .equ key = 0 |
8 | |
9 | .org 0 |
10 | rjmp res |
11 | ;*************************************************************************************************************** |
12 | ;ISR, ca. alle 2mS |
13 | ;*************************************************************************************************************** |
14 | .org OVF0addr |
15 | ISR:in s,sreg |
16 | |
17 | ;----------------------------------------------------- |
18 | ;Taste an Port.C1 entprellen |
19 | ;----------------------------------------------------- |
20 | lsl taste ;Eine 0 in Taste schieben |
21 | sbic pinc,1 ;pinc1 testen |
22 | inc taste ;Wenn nicht gedrückt war, die 0 in eine 1 wandeln |
23 | brne exit ;Nur wenn 8 Nullen in Taste sind, wurde der Taster die letzten 8 ISRs gehalten |
24 | brcc exit ;Wenn vor 9 ISRs noch nicht gedrückt war, Tastenflag (Flanke) setzten |
25 | sbr flags,1<<key |
26 | exit: |
27 | out sreg,s ;Statusbits zurücklesen |
28 | reti ;in der Main weitermachen |
29 | ;*************************************************************************************************************** |
30 | ; --- ENDE ISR --- |
31 | ;*************************************************************************************************************** |
32 | |
33 | res: |
34 | ... ;Deine Init (stack, Ports) |
35 | |
36 | clr flags |
37 | ;------------------------------------- |
38 | ;Timerinterrupt init |
39 | ;------------------------------------- |
40 | ldi temp1,1<<cs00|1<<cs01 ;TC0/64, ISR ca. alle 2mS (8MHz/256/64) |
41 | out TCCR0,temp1 |
42 | ldi temp1,1<<TOIE0 ;Timer0 overflow interrupt |
43 | out TIMSK,temp1 |
44 | ;------------------------------------- |
45 | ;Hauptprogramm |
46 | ;------------------------------------- |
47 | main: |
48 | sbrc flags,key |
49 | rjmp taste_gedr |
50 | |
51 | ... ;Dein Code |
52 | |
53 | rjmp main |
54 | ;------------------------------------- |
55 | ;Taste wurde gedrückt |
56 | ;------------------------------------- |
57 | taste_gedr: |
58 | |
59 | cbr flags,1<<key |
60 | |
61 | ... ;Dein Code |
62 | |
63 | rjmp main |
Jürgen schrieb: > cbr flags,1<<key Ach ja, hier wird das Flag (die Flanke) wieder gelöscht, wenn das nicht passiert, ist es in etwa dasselbe wie ... Jürgen schrieb: > marvin schrieb: >> sbic PIND, PD7 >> rjmp main > > Solange du den Taster hältst, wird rjmp main übersprungen. > Das sind in der Sekunde bei 1 MHz einige 10000 mal.
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.