Forum: Mikrocontroller und Digitale Elektronik Atmega 8 Zähler zählt nicht zurück. entprellen?


von meino (Gast)


Lesenswert?

hallo leute,

ich bin vor ein paar wochen angefangen mich mit avr microkontrollern zu 
befassen und habe mir ein myavr einsteiger set gekauft und mit dem 
lehrbuch schon viel gearbeitet und die beispiele nach programmiert.

Jetzt wollte ich mal etwas selbst erstellen aber habe da so ein paar 
probleme mit.
Ich habe vor eine zugangskontrolle für einen raum zu bauen. als sensoren 
für den eingang habe ich zwei lichtschranken, eine soll zum hoch zählen 
sein und eine zum runter zählen. wenn der zähler oder register ungleich 
0 ist soll ein ausgang auf 1 sein.

Ich habe jetzt mal versucht etwas zu programmieren. die 2 taster auf dem 
testboard habe ich statt der lichtschranken genommen und um den ausgang 
an zu zeigen habe ich eine led auf dem testboard verwendet.

nun mein problem: wenn ich starte ist die led aus, betätige ich kurz 
einen taster geht die led an aber wenn ich den anderen taster wieder 
drücke der den register um 1 verringern soll, geht die led nicht mehr 
aus.

könnt ihr mir vielleicht helfen und sagen wie ich das problem lösen 
kann.

wahrscheinlich muss ich die Taster entprellen aber ich weiß nicht wie es 
Softwaretechnisch am besten geht und an welcher stelle ich die Befehle 
einsetzen muss.

MfG meino

hier mein Programm


;----------------------------------------------------------------------- 
---
; Title         : Assembler Grundgerüst für myAVR-Board
;----------------------------------------------------------------------- 
---
; Funktion      : ...
; Schaltung     : ...
;----------------------------------------------------------------------- 
---
; Prozessor     : ATmega8
; Takt          : 3,6864 MHz
; Sprache       : Assembler
; Datum         : ...
; Version       : ...
; Autor         : ...
;----------------------------------------------------------------------- 
---
.include "AVR.H"
;----------------------------------------------------------------------- 
----
; Reset and Interrupt vector                Beschreibung
begin:   rjmp    main                       ;POWER ON RESET
         reti                               ;Int0-Interrupt
         reti                               ;Int1-Interrupt
         reti                               ;TC2 Compare Match
         reti                               ;TC2 Overflow
         reti                               ;TC1 Capture
         reti                               ;TC1 Compare Match A
         reti                               ;TC1 Compare Match B
         reti                               ;TC1 Overflow
         reti                               ;TC0 Overflow
         reti                               ;SPI, STC Serial Transfer 
Complete
         reti                               ;UART Rx Complete
         reti                               ;UART Data Register Empty
         reti                               ;UART Tx complete
         reti                               ;ADC Conversion Complete
         reti                               ;EEPROM Ready
         reti                               ;Analog Comparator
         reti                               ;TWI (I²C) Serial Interface
         reti                               ;Store Program Memory Redy
;----------------------------------------------------------------------- 
----
; Start, Power ON, Reset
main:    ldi     r16, lo8(RAMEND)
            out     SPL, r16
            ldi     r16, hi8(RAMEND)
            out     SPH, r16
            cbi   DDRD, 2
            sbi   PORTD, 2
            cbi   DDRD, 3
             sbi   PORTD, 3
            ldi   r16, 0b11111111
            out   DDRB, r16
            ldi   r17, 0b00000000

;----------------------------------------------------------------------- 
----
mainloop: wdr
     sbis   PIND, 2
     rjmp   zplus
     sbis   PIND, 3
     rjmp   zminus
              rjmp    mainloop
;----------------------------------------------------------------------- 
----
zplus:       inc   r17
     rjmp   vergleich
zminus:   dec   r17
     rjmp   vergleich

vergleich:     cpi   r17, 0
      brcc   ausgabe
      ldi   r16, 0b00000000
      out   PORTB, r16
      rjmp   mainloop
      brcc   ausgabe
      rjmp   mainloop
ausgabe:      ldi   r16, 0b00000001
      out   PORTB, r16
      rjmp   mainloop

von Karl H. (kbuchegg)


Lesenswert?

meino schrieb:

> nun mein problem: wenn ich starte ist die led aus, betätige ich kurz
> einen taster

so kurz kannst du gar nicht drücken, dass dein µC dieses Drücken nicht 
viele tausend male registriert. Alles was du tust, tust du aus Sicht des 
µC in extremer Zeitlupe.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten

von oldmax (Gast)


Lesenswert?

Hi
Da hat KHB recht. Die Lösung heißt "Flankenerfassung". Da du dich in ASM 
austobst, mal eine kleine Hilfe:
Lese die Eingangsbits in eine Variable. Das macht dich erst mal von der 
Hardware unabhängig. So kannst du am Anfang deiner Programmschleife ein 
Unterprogramm aufrufen, um die Eingänge in eine Variable einzulesen. 
Nennen wir sie New_In. Über eine Exclusiv-Oder Verknüpfung mit em 
vorherigen ( alten) Zustand bekommst du heraus, ob sich ein Bit geändert 
hat. Nennen wir diese Variable Old_In.
Diese Operation geht nur über Register.
Also,
1
    LDS reg_A, New_In
2
    LDS Reg_B, Old_In
3
    EOR Reg_A, Reg_B
4
    BREQ Weiter               ; wenn 0 dann keine Änderung
5
    LDS  REG_B, New_In        ; Reg_A hat das Ergebnis aus EOR
6
    AND  REG_B, Reg_A         ; gesetzte Bits = Flanke von 0 nach 1
7
    STS  Flag_To_High, Reg_B  ; auch in eine Variable eintragen
8
    LDS  Reg_B, Old_In
9
    AND  REG_B, Reg_A         ; gesetzte Bits = Flanke von 1 nach 0
10
    STS  Flag_To_Low, Reg_B  ; auch in eine Variable eintragen
11
Weiter:
12
    LDS  Reg_A, Flag_To_High
13
    ANDI Reg_A, 0b00001000    ; Ist Taste auf Bit 3 betätigt ?
14
    BREQ Weiter1
15
    RCALL Step_Up
16
Weiter1:
17
    LDS  Reg_A, Flag_To_High
18
    ANDI Reg_A, 0b00000100    ; Ist Taste auf Bit 2 betätigt ?
19
    BREQ Weiter2
20
    RCALL Step_down
21
Weiter2:
22
    LDS reg_A, New_In
23
    STS Old_In, Reg_A         ; Und neuen Zustand der Eingänge merken
24
    ....
Nun hast du nur wen ein Signalwechsel erfolgt ist, dir ein Bit gesetzt. 
In der Behandlungsroutine dafür setzt du dieses am Schluß zurück. Damit 
wird diese Routine nur einmal aufgerufen, wen du die Taste beätigst.
1
Step_Up:
2
    LDS Reg_A, Counter
3
    INC Reg_A
4
    STS Counter, Reg_A         ; Tastendruck zählen
5
    LDS Reg_A, Flag_To_High
6
    ANDI Reg_A, 0b11110111     ; Nur Bit 3 auf 0 setzen
7
    STS  Flag_To_High, Reg_A   ; Flag quittieren
8
RET
 Beachte aber, die Signallage bei gedrücktem Taster muss "1" sein. In 
der Regel aber werden Taster aber gegen GND geschaltet, wegen der 
internen Pull-Up Widerstände. Du kannst aber die Signallage anpasen, 
indem du die Eingangsbits vor der Ablage in New_In mit "1" Exclusiv Oder 
verknüpfst.
1
 
2
   In  Reg_A, PinD
3
   LDI Reg_B, 0b11111111
4
   EOR Reg_A, Reg_B
5
   STS New_In, Reg_A
Diese Info sollte erst mal weiterhelfen. zum Entprellen der IO's wirst 
du dir evtl. auch noch Gedanken machen müssen, da diese 
Flankenauswertung dies nicht berücksichtigt.
Gruß oldmax

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.