Code:
.include "m8def.inc"
.equ Summer = PC5
.equ time0 = 256-57
;Adressen im RAM, wo die Tonwerte stehen
.equ ton1 = 0x60
.equ ton2 = 0x61
.equ ton3 = 0x62
.def lpm_reg = r0 ;Hier werden die Werte von db/dw gespeichert
.def tmp = r17 ;Universallregister
.def zaehler = r18 ;Zaehlregister
.org 0x000
rjmp reset ;Am Anfang des Programms erstmal zu "reset:" springen
.org OVF1addr
rjmp zeitumLauf ;Läuft Timer1 über, dann spring zu "zeitumLauf:"
.org OVF0addr
rjmp timerSummer ;Läuft Timer0 über, dann spring zu "timerSummer:"
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 DDRC, Summer ;C.5 als Ausgang
ldi tmp, 0b00000001
out PORTB, tmp ;Am Anfang soll erste LED leuchten
clr zaehler ;Zaehlregister auf 0 setzen
;Tonwerte in den RAM schreiben
;Z-Register mit DW "zeitwerte" füllen
ldi ZH, HIGH(zeitwerte * 2)
ldi ZL, LOW(zeitwerte * 2)
;X-Zeiger zeigt nun auf 0x60
ldi XH,HIGH(ton1)
ldi XL,LOW(ton1)
;Tonwerte in RAM schreiben, da wo X hinzeigt
ldi tmp, 256-57
st X+, tmp
ldi tmp, 256-14
st X+, tmp
ldi tmp, 256-3
st X, tmp
;Timer Register für die Abstände im Lauflicht werden belegt, hier Timer1
ldi tmp, (1<<CS12) | (1<<CS10) ;Prescaler ist 1024
out TCCR1B, tmp
lpm ;Wert von "zeitwerte" in r0 schreiben
mov tmp, lpm_reg ;Wert von r0 in tmp schreiben
push tmp ;LOW-Byte sichern
adiw ZL, 1 ;Z um 1 erhöhen -> zeigt nun auf das HIGH-Byte
lpm
mov tmp, lpm_reg
out TCNT1H, tmp ;HIGH-Byte in TCNT1H schreiben
pop tmp ;gesichertes LOW-Byte wiederholen
out TCNT1L, tmp ;LOW-Byte in TCNT1L schreiben
ldi tmp, (1<<TOIE1) | (1<<TOIE0);Hier werden Interrupts nach Timer1 Überlauf eingeschaltet
out TIMSK, tmp ;Register TIMSK ist dafür zuständig
sei ;Interrupts zulassen
main:
rjmp main ;immer wieder zur "main:" springen
;***************ROUTINE FÜR TIMER1-INTERRUPT***************;
;Z-Zeiger wird auf das erste Element von "zeitwerte" gesetzt
;Wenn zaehler größer oder gleich 6 ist, wird der Zeitwert der
;langsamen zeit geladen
zeitumLauf:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
inc zaehler ;zaehler um 1 erhöhen
;Z-Register auf den 1. Wert zeigen lassen
ldi ZH, HIGH(zeitwerte * 2)
ldi ZL, LOW(zeitwerte * 2)
cpi zaehler, 0b00000110 ;Ist zaehler >= 6?
brsh langzeit ;JA -> langsamen Zeit laden
rjmp LEDpruefen ;NEIN -> spring direkt zu "LEDpruefen:"
;Hier wird nur hingesprungen, wenn das Lauflicht schon 2x schnell
;durchlaufen ist.
;Wenn zaehler = 8 ist, wird wieder der Zeitwert der schnellen
;Zeit geladen und der zaehler wieder auf 0 zurückgesetzt
langzeit:
;Timer0 aktivieren
ldi tmp, (1<<CS02)
out TCCR0, tmp
cpi zaehler, 0b00001001 ;Ist zaehler = 9?
breq clrzaehler ;JA -> springe zu "clrzaehler:"
adiw ZL, 2 ;Z um 2 erhöhen -> zeigt auf das LOW-Byte der
;langsamen Zeit
cpi zaehler, 0b00000110 ;Ist zaehler = 6?
breq ton01 ;1. Tonwert laden
cpi zaehler, 0b00000111 ;Ist zaehler = 7?
breq ton02 ;2. Tonwert laden
cpi zaehler, 0b00001000 ;Ist zaehler = 8?
breq ton03 ;3. Tonwert laden
ton01:
sbiw XL, 2 ;X-Zeiger um 2 vermindern -> auf ton1 zeigen
ld tmp, X
out TCNT0, tmp
rjmp LEDpruefen ;zu "LEDpruefen:" springen
ton02:
adiw XL, 1 ;X-Zeiger um 1 erhöhen -> auf ton2 zeigen
ld tmp, X
out TCNT0, tmp
rjmp LEDpruefen ;zu "LEDpruefen:" springen
ton03:
adiw XL, 1 ;X-Zeiger um 1 erhöhen -> auf ton3 zeigen
ld tmp, X
out TCNT0, tmp
rjmp LEDpruefen ;zu "LEDpruefen:" springen
clrzaehler:
;Timer0 abstellen
ldi tmp, (0<<CS02)
out TCCR0, tmp
clr zaehler ;zaehler wieder auf 0 setzen
;Prüfen, ob letzte LED an ist, wenn das der Fall ist, dann wieder
;die erste LED an machen, sonst um 1 nach links rücken
LEDpruefen:
in tmp, PINB
cpi tmp, 0b00000100 ;Ist letzte LED an?
breq ersteLED ;JA -> spring zu "ersteLED:"
lsl tmp ;tmp mit 2 multiplizieren -> jedes Bit verschiebt
;sich um 1 nach links
rjmp zeitumEnde ;zum Ende der Routine springen
ersteLED:
ldi tmp, 0b00000001 ;wieder erste LED anmachen
zeitumEnde:
out PORTB, tmp ;den aktuellen LED-Status an PORTB ausgeben
;Timer1 neu laden
lpm ;Wert von "zeitwerte" in r0 schreiben
mov tmp, lpm_reg ;Wert von r0 in tmp schreiben
push tmp ;LOW-Byte sichern
adiw ZL, 1 ;Z um 1 erhöhen -> zeigt nun auf das HIGH-Byte
lpm
mov tmp, lpm_reg
out TCNT1H, tmp ;HIGH-Byte in TCNT1H schreiben
pop tmp ;gesichertes LOW-Byte wiederholen
out TCNT1L, tmp ;LOW-Byte in TCNT1L schreiben
pop tmp
out SREG, tmp ;SREG wiederholen
pop tmp ;tmp wiederholen
reti ;Gehe wieder dahin, wo du hergekommen bist
timerSummer:
push tmp ;tmp sichern
in tmp, SREG
push tmp ;SREG sichern
sbis PORTC, Summer ;Ist C.5 = 1?
rjmp umschalten ;NEIN -> auf 1 setzen
cbi PORTC, Summer ;JA -> auf 0 setzen
rjmp summerEnde ;zum Ende der Routine springen
umschalten:
sbi PORTC, Summer
summerEnde:
;Timer0 neu laden
ld tmp, X
out TCNT0, tmp
pop tmp
out SREG, tmp ;SREG wiederholen
pop tmp ;tmp wiederholen
reti ;Gehe wieder dahin, wo du hergekommen bist
;Das sind die Werte, womit der Timer1 (Lauflicht-Timer) vorgeladen wird
;Anzahl der Werte muss GERADE sein
zeitwerte:
.dw 65536-1000, 65536-3600
Lesezeichen