Code:
;Dieses Programm produziert ein Lauflicht. Jede halbe Sekunde geht die
;nächste LED an. Drückt man den Taster, ändert sich die Richtung des Lauflichtes
;Das Programm läuft in einer Endlosschleife durch.
;Problem des Prellens soll hier nicht mehr auftreten.
.include "m8def.inc"
.equ time1 = 65536-1 ;Damit wird der Timer1 vorgeladen, für 100ms
.equ Taster = PD2 ;Taster an D.2
.equ sperre = 7 ;Taster sperren (Hilfsvariable)
.equ laufrichtung = 0
.def tmp = r16 ;Mein Universallregister
.def statusLED = r17 ;In diesem Register wird gespeichert, welche LED gerade leuchtet
.def statusTaster = r18 ;Statusregister, wo die Sperre gespeichert ist
.def zaehler = r19 ;Mein Zählregister, hier zähl ich hoch,
;damit ich auf eine halbe Sekunde komme
.org 0x000
rjmp reset ;Interruptvektor "reset:"
.org OVF1addr
rjmp zeitum ;Interruptvektor für Timer1 Überlauf
reset:
;Stack einrichten
ldi tmp, HIGH(RAMEND) ;HIGH-Byte der obersten RAM-Adresse
out SPH, tmp
ldi tmp, LOW(RAMEND) ;LOW-Byte der obersten RAM-Adresse
out SPL, tmp
ldi tmp, 0b11111111
out DDRB, tmp ;PortB als Ausgang
sbi PIND, Taster ;D.2 Pullups aktivieren
cbi PIND, Taster ;D.2 als Eingang
ldi statusLED, 0b00000100
out PORTB, statusLED ;Am Anfang soll erste LED leuchten
ldi zaehler, 0b00000000 ;Zähler auf 0 stellen
;Timer Register für 100ms werden belegt, hier Timer1
ldi tmp, (1<<CS12) | (1<<CS10) ;Prescaler ist 1024
out TCCR1B, tmp
ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
ldi tmp, LOW(time1) ;für die 1/2 speichern ->
out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
ldi tmp, (1<<TOIE1)
out TIMSK, tmp
sei ;Interrupts zulassen
main:
cpi zaehler, 0b00000101 ;Ist zaehler = 5?
breq lauflicht ;JA -> springe zu lauflich
rjmp main ;NEIN -> springe zu main
lauflicht:
clr zaehler ;zaehler auf 0 setzen
sbrs statusTaster, laufrichtung ;Ist Bit0 = 1?
rjmp pruefRechts ;NEIN -> laufe rechtsrum
;JA -> lauf linksrum
pruefLinks:
cpi statusLED, 0b00000100 ;Leuchtet 3. LED?
breq wiederholenLinks ;Wenn JA, spring zu "wiederholen"
lsl statusLED ;Wenn NEIN´, Bit nach links verschieben -> nächste LED
rjmp ende ;spring zu ende
pruefRechts:
cpi statusLED, 0b00000001 ;Leuchtet 1. LED?
breq wiederholenRechts ;Wenn JA, spring zu "wiederholen"
lsr statusLED ;Wenn NEIN, Bit nach rechts verschieben -> vorherige LED
rjmp ende ;spring zu ende
wiederholenLinks:
ldi statusLED, 0b00000001
rjmp ende
wiederholenRechts:
ldi statusLED, 0b00000100
ende:
out PORTB, statusLED ;nächste LED leuchtet
rjmp main ;springe wieder zur main
;*****************INTERRUPTROUTINE FÜR TIMER1***************************
zeitum:
push tmp ;Rette Universallregister
out SREG, tmp ;Rette Statusregister
push tmp
inc zaehler ;Zähler erhöhen
sbis PIND, Taster ;Ist Taste gedrückt?
rjmp zeitum1 ;NEIN -> springe zu zeitum1
zeitum0: ;JA -> hier weiter machen
sbrs statusTaster, sperre ;Ist Sperre gesetzte?
rjmp zeitum2 ;NEIN -> springe zu zeitum1
rjmp zeitum3 ;JA -> springe zu zeitum2
zeitum1:
cbr statusTaster, (1<<sperre) ;Sperre löschen
rjmp zeitum3
zeitum2:
sbr statusTaster, (1<<sperre) ;Sperre setzen
;Aktion durchführen die beim Drücken des Tasters passieren soll
sbrs statusTaster, laufrichtung ;Ist Bit0 = 1?
rjmp setzeBitLauf ;NEIN -> auf 1 setzen
cbr statusTaster, (1<<laufrichtung);JA -> auf 0 setzen
rjmp zeitum3 ;Ende der Routine
setzeBitLauf:
sbr statusTaster, (1<<laufrichtung)
zeitum3:
;Timer1 neu laden
ldi tmp, HIGH(time1)
out TCNT1H, tmp
ldi tmp, LOW(time1)
out TCNT1L, tmp
pop tmp ;stelle SREG wieder her
out SREG, tmp
pop tmp ;stelle Universalregister wieder her
reti ;die Interrupt-Routine wird verlassen
;und es wird weiter im Hauptprogramm gearbeitet
An was kann das denn noch alles liegen?
Lesezeichen