Es geht
Er spielt die 3 Töne hintereinander ab (immer 1 Sekunde) und dann hört er auf.
Hier der Code:
Code:
;Programm
;CDurTonleiter rauf und runter spielen
.include "m8def.inc"

.def tmp = r16               	;Mein Universallregister
.def zaehlerSek = r17			;Mein Zählregister
.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 DB "tonleiter1" füllen
   	ldi ZH, HIGH(tonleiter1 * 2)
   	ldi ZL, LOW(tonleiter1 * 2)	
	
	sbi DDRB, Summer			;B.2 als Ausgang
	sbi PORTB, Summer			;B.2 auf HIGH stellen	

   	sei                    		;Interrupts zulassen

;Hier wird der nächste Ton geladen und in "tonwert" gespeichert
;Z-Zeiger wird um 1 erhöht, damit er beim nächsten mal den nächsten
;Ton lädt. Es wird hier auch verglichen,, ob der letzte Ton erreicht,
;wenn ja, dann springt er zu "endeTon"
tonLaden:
	clr zaehlerSek				;ZählerSek 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					;sonst springe zu "main:"

;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
endeTon:
	ldi tmp, (0<<CS02)         	;Timer stoppen 
   	out TCCR0, tmp

;Die Hauptschleife, die sich immer wiederholt
main:
	cpi zaehlerSek, 0b00101000	;ist zaehlerSek = 40 (also 1 Sekunde um?)
	breq tonLaden				;wenn ja, dann lade den nächsten Ton
	rjmp main					;immer wieder zurück zu main springen

;Läuft Timer2 über, so wieder zaehlerSek um 1 erhöht und
;Timer2 neu vorgeladen
pruefSek:
	push tmp					;tmp sichern
	in tmp, SREG
	push tmp					;SREG sichern
		inc zaehlerSek         ;ZählerSek um 1 erhöhen 
      	ldi tmp, time2         ;Hier wird der Timer vorgeladen 
      	out TCNT2, tmp
	pop tmp
	out SREG, tmp				;SREG wiederholen
	pop  tmp					;tmp wiederholen
	reti						;Spring wieder dahin, wo du hergekommen bist

;Läuft Timer0 über, so wird B.2 umgeschaltet, sodass Ton
;aus dem Summer zu hören ist
timerSummer: 
   push tmp               		;tmp sichern 
   in tmp, SREG 
   push tmp 					;SREG sichern
      sbis PINB, Summer         ;ist B.2 = 1?
      rjmp timerSummer1         ;NEIN -> spring zu timerSummer1:" 
      cbi PORTB, Summer         ;JA -> setze B.2 auf 0 
      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 

timerSummer3: 
   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 256-117, 256-16, 256-2, 0	;Werte zum Vorladen des Timers für die Töne
									;c', a' und c''
Ich hoffe, er ist nicht wieder so unübersichtlich.

Musste aber "daten_laenge" auf 4 stellen, da er sonst nach dem 2. Ton schon aufgehört hätte. Liegt also daran, wie man das programmiert, ob man da nun 3 oder 4 stehen hat. Bei Tekeli hab ich gar keine daten_laenge mehr gesehen, hast es wohl ganz anders gemacht, oder?
So, das Label "tonLaden:" steht vor der main, da er da zuerst hingehen muss, um den ersten Ton zu laden. Ich hoffe, das ist ok so.

Also dann schreibt mal bitte eure Meinungen zu meinem Code.

Sorry nochmals, dass ich uns aufgehalten habe.

Tekeli: Darf ich mal fragen, wie lang du schon in Assembler programmierst?

Gruß
Thomas