Forum: Mikrocontroller und Digitale Elektronik Taster,Atmega 8


von marvin (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von XXX (Gast)


Lesenswert?

Hallo

Vielleicht geht die LED ganz schnell an/aus/an/aus,
weil dein Taster prellt??

Gruß
Joachim

von marvin (Gast)


Lesenswert?

"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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von marvin (Gast)


Lesenswert?

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

von marvin (Gast)


Lesenswert?

aso sry ich habe natürlich meinen Taster nicht entprellt, ich wollt nur 
ein Feedback für mein Programm

von Jürgen (Gast)


Lesenswert?

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.

von Jürgen (Gast)


Lesenswert?

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.

von marvin (Gast)


Lesenswert?

>"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

von Jürgen (Gast)


Lesenswert?

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.

von Jürgen (Gast)


Lesenswert?

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

von Jürgen (Gast)


Lesenswert?

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.

von Jürgen (Gast)


Lesenswert?

Ups, vor der main, noch den Befehl "sei" einfügen.

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
Noch kein Account? Hier anmelden.