Hallo,
hier ist der Code für den Taster...
der erste Code ist ohne Timer, man kann daran schön erkennen, was Prellen ist.
Ob man die LED eingeschaltet bekommt, ist manchmal eine reine Glücksache
Code:
.include "m8def.inc"
.equ sperre = 7 ;Taster sperren
.equ LED = PD7
.equ Taster = PD4
.def tmp = R16
.def status = R17
.org 0x000
rjmp reset
reset:
ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
sbi DDRD,LED
cbi DDRD,Taster
sbi PORTD,Taster
sbi PORTD,LED
loop:
sbis PIND,Taster
rjmp loop0
cbr status,(1<<sperre)
rjmp loop
loop0:
sbrc status,sperre
rjmp loop
sbis PORTD,LED
rjmp loop1
cbi PORTD,LED
sbr status,(1<<sperre)
rjmp loop
loop1:
sbi PORTD,LED
sbr status,(1<<sperre)
rjmp loop
Sorry, ich war zu faul um hier komentare zu schreiben [-X
Und jetzt nochmal das selbe nur mit Timer 0 der alle 26 mS die Taste abfragt.
Hier kann kann sich die Finger wunddrücken, kein Prellen mehr da
Die 26 mS sind auch nicht kritisch, es könnten auch 100 sein, oder schafst Du das einen Taster 10 mal in der Sekunde zu drücken [-(
Achso, Du mußt natürlich noch Deine Ports und Pins anpassen, ich habe, glaube ich vergessen die in der equs oben eizutragen.
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tasterschaltung mit einem Timer ;;
;; Quarz 10 MHz ;;
;;Der Timer hat einen prescaller von 1024 das heißt der hat eine ;;
;; Frequenz von 9,76 kHz. Da ich Ihn noch mit 1 vorlade muß er ;;
;; 254 mal durchlaufen um ein Interrupt auszulösen, das wäre etwa;;
;; 38,5 Hz bzw. 26 ms Achtung, es ist auf 10 Mhz ausgelegt, müßte;;
;; aber auch bei anderen Frequenzen klappen nur die Zeiten sind ;;
;; natürlich anders. ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.include "m8def.inc"
.equ time = 255 -254 ;Damit wird der Timer vorgeladen
.equ sperre = 7 ;Taster sperren (Hilfsvariable)
.equ LED = PD7 ;kein komentar
.equ Taster = PD4 ;kein komentar
.def tmp = R16 ;mein universallregister
.def status = R17 ;Das ist mein Statusregister, wo später die sperre
;gespeichert wird, man sehe es sind noch 7 Bits
;für andere Zwecke frei
.org 0x000
rjmp reset ;Interruptvektor reset kein komentar
.org OVF0addr
rjmp zeitum ;Interruptvektor für Timer0 Überlauf, hier
;spring mein Programm hin, wenn der Timer überläuft
reset:
;;Stack einrichten
ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
;;Port D ist bei mir mit LED und mit einem Taster belegt
;;PD7 ist die Diode, PD4 ist der Taster
sbi DDRD,LED ;kein komentar
cbi DDRD,Taster ;kein komentar
sbi PORTD,Taster;Pullup am Taster
sbi PORTD,LED ;Da ich meine LED gegen VCC geschaltet habe
;mache ich sie hier aus
;;Timer Register werden belegt
;;Ich nehme hier den Timer 0
ldi tmp,(1<<CS02) | (1<<CS00) ;prescaller ist 1024
out TCCR0,tmp ;Register TCCR0 ist für den Prescaller zuständig
ldi tmp,(1<<TOIE0);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
out TIMSK,tmp ;Register TIMSK ist dafür zuständig
ldi tmp,time ;Hier wird der Timer vorgeladen und zwar mit 255-254
out TCNT0,tmp ; Er läuft 254 mal durch bevor ein Interrupt auftritt
sei ;mein Lieblingsfehler, na was den Interrupts allgemein zulassen
loop: ;meine Hauptschleife
rjmp loop ;Hier herscht totale langeweile
;;Die Routine wird abgearbeitet wenn ein Interrupt stattgefunden hat
zeitum:
push tmp ;Rette universallregister, hier ziemlich sinnlos
;aber Ordnung muß sein
in tmp,SREG ;rette Statusregister, sehe eine Zeile höher
push tmp ;sehe eine Zeile höher
sbis PIND,Taster ;Überspringe nächste Zeile, wenn PIND HIGH ist
;also nicht gedrückt
rjmp zeitum0 ;sonst springe nach zeitum0
cbr status,(1<<sperre) ;Lösche meine Sperre (Bit 7 im Register status)
rjmp zeitum2 ;Springe nach zeitum2
zeitum0:
sbrc status,sperre ;Überspringe nächste Zeile, wenn Sperre nicht gesetzt ist
rjmp zeitum2 ;Springe nach zeitum2
sbis PORTD,LED ;Überspringe nächste Zeile, wenn LED gesetzt(aus) ist
rjmp zeitum1 ;springe nach zeitum1
cbi PORTD,LED ;Schalte LED ein
sbr status,(1<<sperre) ;setze Sperre(Bit 7 im Register status)
rjmp zeitum2 ;Springe nach zeitum2
zeitum1:
sbi PORTD,LED ;Schalte LED aus
sbr status,(1<<sperre) ;setze Sperre(Bit 7 im Register status)
zeitum2:
ldi tmp,time ;Hier war der Fehler und zwar muß
out TCNT0,tmp ; der Timer neugeladen werden(genauso wie im reset)
pop tmp ;Stelle SREG wieder her
out SREG,tmp ;sehe eine Zeile höher
pop tmp ;Stelle universallregister wieder her
reti ;die Interrupt Routine wird verlassen, und
;es wird weiter im Hauptprogramm gearbeitet
Hier habe ich alles ausreichend kommentiert.....
achso, ich hatte gerade 10 MHz Quarz drauf, es müßte aber mit anderen Frequenzen auch klappen.
Wenn Du noch fragen hast, dann frag.
Sollte jemand weitere Anregungen haben, würde ich mich sehr freuen
Gruß Sebastian
Lesezeichen