Code:
;Programm
;CDurTonleiter rauf und runter spielen
.include "m8def.inc"
.def tmp = r16 ;Mein Universallregister
.def zaehlerSek = r17 ;Mein Zählregister
.def zaehlerTon = r18 ;Mein Zählregister, um zu prüfen, ob alle Töne geladen wurden
.def tonwert = r19 ;aktueller Wert für den Ton
.def lpm_reg = r0 ;Mein lpm-Register
.equ Summer = PB2 ;Summer an B.2
.equ time0 = 256-255 ;Timer0 für die Tonleiter
.equ time2 = 256-90 ;Damit wird der Timer2 vorgeladen, für die Sekunde
.equ daten_laenge = 4 ;Anzahl der Werte
.org 0x000
rjmp reset ;Interruptvektor "reset:"
.org OVF2addr
rjmp pruefSek ;Interruptvektor "pruefSek:"
.org OVF0addr
rjmp timerSummer ;Interruptvektor "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
;Timer Register für Ton werden belegt, hier Timer 0
ldi tmp, (1<<CS02) ;Prescaler ist 512
out TCCR0, tmp ;Register TCCR0 ist für den Prescaller zuständig
ldi tmp, time0 ;Hier wird der Timer vorgeladen
out TCNT0, tmp
;Timer Register für Sekunde werden belegt, hier Timer 2
ldi tmp, (1<<CS22) | (1<<CS21) | (1<<CS20) ;Prescaler ist 1024
out TCCR2, tmp ;Register TCRR2 ist für den Prescaller zuständig
ldi tmp, (1<<TOIE0) | (1<<TOIE2);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
out TIMSK, tmp ;Register TIMSK ist dafür zuständig
;Z-Register mit daten1 füllen
ldi ZH, HIGH(tonleiter1 * 2)
ldi ZL, LOW(tonleiter1 * 2)
ldi zaehlerSek, 0b00000000 ;ZählerSek auf 0 setzen
sbi DDRB, Summer ;B.2 als Ausgang
sbi PORTB, Summer ;B.2 auf HIGH stellen
sei ;Interrupts zulassen
;Die Hauptschleife
main:
cpi zaehlerSek, 0b00010100 ;wenn ZählerSek != 40 ist
brne main ;dann immer wieder zu "main:" springen
;Wenn eine Sekunde um ist, dann springe hier rein
;und prüfe, ob es noch einen Wert für die Tonleiter
;zu laden gibt, wenn nicht, spring wieder zurück zu main
pruefTonleiter:
clr zaehlerSek ;Zähler auf 0 setzen
cpi zaehlerTon, 0b11111111 ;Wenn ZählerTon != 255 ist
brne ladeTon ;dann spring zu "ladeTon:"
rjmp main ;sonst wieder zurück zu "main:"
;Wird aufgerufen, wenn Timer2 überläuft (Timer für Sekunde)
;Hier wird das Zählregister für den Timer um 1 erhöht und der
;Timer neu geladen
pruefSek:
push tmp ;tmp sichern
in tmp, SREG ;SREG sichern
push tmp
inc zaehlerSek ;ZählerSek um 1 erhöhen
ldi tmp, time2 ;Hier wird der Timer vorgeladen
out TCNT2, tmp
pop tmp ;SREG wiederholen
out SREG, tmp
pop tmp ;tmp wiederholen
reti ;wieder dahin, wo du hergekommen bist
;Wenn 1 Sekunde vorbei ist und es noch einen Ton gibt,
;der noch nicht geladen ist dann springe hier hin und
;lade den nächsten Wert von der Datenbank "tonleiter"
ladeton:
clr zaehlerSek ;Zähler wieder auf 0 setzen
lpm ;Daten von tonleiter1: holen
mov tonwert, lpm_reg ;erstes Byte in tmp verschieben
adiw ZL,1 ;Z um 1 erhöhen, nächstes Byte
ldi tmp, LOW ((tonleiter1 * 2) + daten_laenge) ;vergleiche LOW-Byte
cp ZL, tmp
ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte
cpc ZH, tmp
breq endeTon ;springe zu "endeTon:", wenn letztes Byte ausgelesen
rjmp main ;wieder zurück zur "main:"
;Wenn alle Töne geladen sind, dann wird das Register "zaehlerTon"
;auf 255 gesetzt
endeTon:
ldi zaehlerTon, 0b11111111 ;ZählerTon auf 255 setzen -> keine weiteren Wert
;mehr von "tonleiter1:" holen
rjmp main ;wieder zurück zu "main:"
;Wird aufgerufen, wenn Timer0 überläuft (Timer für Ton)
;Hier wird geprüft, ob an B.2 HIGH oder LOW anliegt
;und dementsprechend umgesetzt
timerSummer:
push tmp ;tmp sichern
in tmp, SREG ;SREG sichern
push tmp
sbis PINB, Summer ;überspringe, wenn B.2 = 1 ist
rjmp timerSummer1 ;wenn B.2 = 0 ist, dann spring zu "umschalten1:"
cbi PORTB, Summer ;wenn B.2 = 1 ist, dann B.2 auf 0 setzen
rjmp timerSummer2 ;zu "timerSummer2:" springen
timerSummer1:
sbi PORTB, Summer ;wenn B.2 = 0 ist, dann auf 1 setzen
;Hier wird Timer0 mit dem aktuellen Tonwert vorgeladen
timerSummer2:
out TCNT0, tonwert ;Timer dementsprechen vorladen
rjmp timerSummer4 ;zu "timerSummer4:" springen
timerSummer4:
pop tmp ;SREG wiederholen
out SREG, tmp
pop tmp ;tmp wiederholen
reti
;Das sind die Werte, womit der Timer0 (Tonleiter-Timer) vorgeladen wird
tonleiter1:
.db 255-28, 255-16, 255-14, 0 ;Werte zum Vorladen des Timers für die Töne
;c', a' und c''
Hier nochmal der aktuelle Code.
Lesezeichen