Moin moin,

@Masters
Danke fuer die Pdf's. Die sind wirklich sehr gut!
Und danke für den Bug-Hinweis.
Um AVRStudio zu benutzen, kann ja Sebastian unter Linux VMware einsetzen. Das funktioniert sehr gut!

@Thomas
siehe mal, was man hier so alles findet
https://www.roboternetz.de/phpBB2/dl...le&file_id=169

Und hier ist die bereinigte Version. Ich schalte die beiden Timer am Ende aus, damit der uC auch in der Looping-Schleife bleibt.
Code:
.include "m8def.inc"

;; Wir wollen mit dem Timer2 einen Interrupt pro Sekunde ausloesen.
;; Asuro hat einen 8MHz Quarz. Wir waehlen eine Prescaler von 1024 aus( 8, 32, 64, 128, 256, 1024)
;; 8MHz/1024 = 8000000Hz/1024 = 7812,5 Hz die Timerfrequenz.
;; -> ein Timerschritt dauert 1/7812,5 = 0,000128s = 128us.
;; -> Fuer eine Sekunde muessten also 1s/128us = 7812 Timerschritte ausgef?hrt werden.
;; Da das nur ein 8-bit Timer ist, macht er 256 Schritte zum Ueberlauf.
;; -> Des wegen barauchen wir eine Hilfsvariable,
;; um speichern zu koennen , wieviele Ueberlaeufe er schon hinter sich hat.
;; -> 7812 = 36 * 217
;; -> 36 mal soll der Timer bis 217 Zahlen -> dann ist eine Sekunde vergangen
.EQU TIMER2 = 256 - 217	
.EQU counts2 = 36

.EQU FRONT_LED		= PD6	; Dran haengt auch ein Summer :)

.DEF erg		= R0	; Das Register wird vom LPM-Befehl benutzt
.DEF tmp 		= R16	; Fuer algemeine Zwecke
.DEF counter2 		= R17	; Hier speichern wir, wieviele Ueberlaufe der Timer2 schon hatte
.DEF frequence		= R18	; Hier wird die aktuelle Frequenz des Summers gespeichert


.CSEG
.ORG 0x000
	RJMP RESET   	; Interruptvektor reset

.ORG OVF2addr		; Interruptvektor fuer Timer2 Ueberlauf.
	RJMP TIM2_OVR	; Dahin wird gesprungen, wenn der Timer2 ueberlaeuft

.ORG OVF0addr		; Interruptvektor fuer Timer0 Ueberlauf.
   	RJMP TIM0_OVR	; Dahin wird gesprungen, wenn der Timer0 ueberlaeuft


RESET:
	;; Initializierung des Stackpointers
	LDI tmp, LOW(RAMEND)			; LOW-Byte der obersten RAM-Adresse
	OUT SPL, tmp
	LDI tmp, HIGH(RAMEND)			; HIGH-Byte der obersten RAM-Adresse
	OUT SPH, tmp


	SBI DDRD,FRONT_LED			; Der Pin an dem die FrontLed und jetzt der Summer haengen
						; als Ausgang definieren

	LDI frequence, 255			; Die zahl mit dem der Counter vom Timer0 geladen wird

	;; Timer2 Register werden belegt
	;; Es wird Timer2 benutzt
   	LDI tmp,(1<<CS22)|(1<<CS21)|(1<<CS20)	; Prescaller ist 1024. Also Lade (0000 0100 V 0000 0010 V 0000 0001) = 0000 0111 in tmp
	OUT TCCR2,tmp   			; Register TCCR2 ist fuer den Prescaller zustaendig (siehe Datenblatt)
	LDI tmp,TIMER2 				; Hier wird der Timer2 vorgeladen und zwar mit TIMER2. Siehe oben.
	OUT TCNT2,tmp	  			; Er laeuft counts2 mal durch bevor ein Interrupt auftritt. Siehe CPI- Vergleich in main
	
	;; Timer0 Register werden belegt
	;; Es wird Timer0 benutzt
   	LDI tmp,(1<<CS01) | (1<<CS00)	; Prescaller ist 64. Also Lade (0000 0010 V 0000 0001) = 0000 00011 in tmp
	OUT TCCR0,tmp   		; Register TCCR0 ist fuer den Prescaller zustaendig (siehe Datenblatt)
	
	OUT TCNT0,frequence   		; Counter vom Timer0 laden. 
	
	LDI tmp,(1<<TOIE2) | (1<<TOIE0)	; Hier werden Interrupts fuer einen Ueberlauf von Timer2 bzw. Timer0 eingeschaltet
	OUT TIMSK,tmp   		; Register TIMSK ist dafuer zustaendig
	
	LDI ZH,HIGH(2*toene)		; Lade die Adresse unserer Daten in das z-Register
	LDI ZL,LOW(2*toene)		; "2*" - es ist so :)
	
	SEI      			; Interrupts allgemein zulassen

main:
	CPI counter2, counts2		; Vergleiche ob der Timer2 schon counts2 mal durchgelaufen hat
	BREQ switch_frequence		; Wenn ja, gehe zu switch_frequnce
	RJMP main			; sonts Looping

switch_frequence:
	CLR counter2			; Counter2 auf 0 setzen. Der Timer2 soll wieder counts2 mal durchlaufen
		
	LPM				; Lese ein Byte aus dem Programmspeicher - Naechster Tonewert
	TST erg                         ; R0 auf 0 testen
        BREQ ende			; Ein ja bedeutet, dass wir am Ende sind -> Ende
	
	LDI frequence, 255		; Kein Kommentar
	SUB frequence, erg		; Rechne den entsprechenden Wert fuer den Counter
	OUT TCNT0, frequence		; Beschreibe den Counter von Time0 mit dem Wert
	
	ADIW ZL,1			; Pointer auf das naechste Byte
	RJMP main			; Kehre zurueck zum main
	
ende:
	LDI tmp,(0<<CS02)|(0<<CS01)|(0<<CS00)	; Den Timer0 ausschalten
	OUT TCCR0,tmp   			; Register TCCR0 ist dafuer zustaendig (siehe Datenblatt)
	LDI tmp,(0<<CS22)|(0<<CS21)|(0<<CS20)	; Den Timer2 ausschalten
	OUT TCCR2,tmp   			; Register TCCR2 ist dafuer zustaendig (siehe Datenblatt)

looping:	
	RJMP looping			; Die unendliche Geschichte :)
	
TIM2_OVR:
	PUSH tmp			; Benutztes Register auf den Stack
	IN tmp, SREG			; Zustand des Statusregisters einlesen
	PUSH tmp			; Ebenfalls auf den Stack ablegen
	
	INC counter2			; Der Timer2 hat wieder mal einen Ueberlauf
	
	LDI tmp, TIMER2         	; Kein Kommentar
	OUT TCNT2, tmp          	; Conuter vom Timer2 erneut laden
	
	POP tmp				; Alten SREG-Inhalt vom Stapel holen
   	OUT SREG, tmp 			; und das Statusregister wiederherstellen
   	POP tmp				; tmp wiederherstellen
	RETI				; Setzte das durch den Interrupt unterbrochenes Programm fort
	

TIM0_OVR:
	PUSH tmp			; Benutztes Register auf den Stack
	IN tmp, SREG			; Zustand des Statusregisters einlesen
	PUSH tmp			; Ebenfalls auf den Stack ablegen
	
	SBIC PIND,FRONT_LED		; Was ist auf dem PIND6? 
	RJMP off			; Wenn 1, dann schalte auf 0
	RJMP on				; Wenn 0, dann schalte auf 1
off:	
	CBI PORTD,FRONT_LED		; schalte auf 0
	RJMP exit			; gehe zu exit
on:
	SBI PORTD,FRONT_LED		; schalte auf 1
exit:	
	OUT TCNT0,frequence		; Conuter vom Timer0 erneut laden
	
	POP tmp				; Alten SREG-Inhalt vom Stapel holen
   	OUT SREG, tmp 			; und das Statusregister wiederherstellen
   	POP tmp				; tmp wiederherstellen
	RETI				; Setzte das durch den Interrupt unterbrochenes Programm fort	

toene:
.DB 213, 234, 150, 34, 123, 45, 123, 100, 80, 200, 214, 0 ; ich hatte keine Lust die richtigen Tonwerte auszurechenn :)
So, wann kommt die naechste Aufgabe?
Best wishes