Code:
	.NOLIST                    ; List-Output unterdrücken
 .INCLUDE <m32def.inc>       ; das gibt es für jeden Controllertyp
 .LIST                      ; List-Output wieder aufdrehen
 .CSEG                      ; was nun folgt, gehört in den FLASH-Speicher
.def tmp           = r16
.def count0    	   = r17
.def count1    	   = r18
.def count2    	   = r19
.def compare_value = r23
.def reload        = r24
.def softcounter   = r25
.def sollwert	   = r20
.def pulseMotor2   = r21
.def calc		   = r22
.def sollwert_M1   = r0
.def pulseMotor1   = r1
.def compare_value_M1 = r2
.equ LED   	   = PC7
.equ Taster4   = PD2
.equ Taster6   = PD3
.equ PWM_1     = PD4
.equ PWM_2     = PD5
.equ Pulse1    = PB0
.equ Pulse2    = PB2
.equ Richtung1 = PB1
.equ Richtung2 = PB3
.EQU  clk = PA4
.EQU  richtung = PA5
.EQU  strom = PA6
 ;------------------------------------------------------
 ;     Warteschleife ca. 1 ms multipliziert 
 ;     mit dem übergebenen Parameter
 ;------------------------------------------------------
.MACRO  warten 
        ldi  count0, @0   ; Lade direkten Wert in R17 1 Zyklus
LOOP2:  ldi  count1, 100   ; Lade direkten Wert in R18 1 Zyklus
LOOP1:  ldi  count2, 52   ; Lade direkten Wert in R19 1 Zyklus
LOOP0:  dec  count2        ; Dekrementiere R19 -> Z ist gesetzt, wenn R19 == 0
						; 1 Zyklus
        brne LOOP0   	; Teste Zero Flag (Z) 
		                ; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
        dec  count1	  	; Dekrementiere R18 -> Z ist gesetzt, wenn R18 == 0
						; 1 Zyklus
        brne LOOP1   	; Teste Zero Flag (Z) 
		                ; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
        dec  count0       	; Dekrementiere R17 -> Z ist gesetzt, wenn R17 == 0
						; 1 Zyklus
        brne LOOP2   	; Teste Zero Flag (Z) 
.ENDM
.MACRO  warten10msMalX 
        ldi  count0, @0   ; Lade direkten Wert in R17 1 Zyklus
LOOP2:  ldi  count1, 226   ; Lade direkten Wert in R18 1 Zyklus
LOOP1:  ldi  count2, 235   ; Lade direkten Wert in R19 1 Zyklus
LOOP0:  dec  count2        ; Dekrementiere R19 -> Z ist gesetzt, wenn R19 == 0
						; 1 Zyklus
        brne LOOP0   	; Teste Zero Flag (Z) 
		                ; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
        dec  count1	  	; Dekrementiere R18 -> Z ist gesetzt, wenn R18 == 0
						; 1 Zyklus
        brne LOOP1   	; Teste Zero Flag (Z) 
		                ; 1 Zyklus, wenn wahr, 2 Zyklen, wenn falsch
        dec  count0       	; Dekrementiere R17 -> Z ist gesetzt, wenn R17 == 0
						; 1 Zyklus
        brne LOOP2   	; Teste Zero Flag (Z) 
.ENDM
 ;------------------------------------------------------
 ;     Start Adresse 0000
 ;------------------------------------------------------
 RESET:
     jmp INIT           ; springen nach "INIT"
 ;------------------------------------------------------
 ;     ISR VECTORS
 ;------------------------------------------------------
.ORG 0x002
    jmp EXTERN0       ;Interruptvektor für INT0, hier
                      ;spring das Programm hin, wenn an Pin D.2 ein Flankenübergang
					  ;erfolgt.
.ORG 0x004
    jmp EXTERN1       ;Interruptvektor für INT1, hier
                      ;spring das Programm hin, wenn an Pin D.3 ein Flankenübergang
					  ;erfolgt.
.ORG 0x006
    jmp EXTERN2       ;Interruptvektor für INT2, hier
                      ;spring das Programm hin, wenn an Pin B.2 ein Flankenübergang
					  ;erfolgt.
.ORG 0x012
    jmp Timer1OVF     ;Interruptvektor für Timer1, hier
                      ;spring das Programm hin, wenn Timer 1 überläuft
					  
 .ORG INT_VECTORS_SIZE    ; dadurch haben wir für die Vektoren Platz gelassen
 INIT:  
 ;------------------------------------------------------
 ;     INITIALIZE
 ;------------------------------------------------------
     ldi tmp,high(RAMEND)     ;Stack Pointer setzen 
     out SPH,tmp              ; "RAMEND" ist in m32def.inc (s.o.) festgelegt
     ldi tmp,low(RAMEND)      ; 
     out SPL,tmp              ;
 ;------------------------------------------------------
 ;   eigene Initialisierungen
 ;------------------------------------------------------
    
	LDI tmp, 0
	LDI tmp, (1<<PWM_1)|(1<<PWM_2)  ; PWM Bits auf eins
    OUT DDRD, tmp                   ; das kommt ins Control-Register f. PortD
                                    ; dadurch sind Pullups an Port an					  
    LDI tmp, 0
    LDI tmp, (1<<Richtung1)|(1<<Richtung2) ; Richtungs Bits auf eins
    OUT DDRB, tmp                          ; das kommt ins Control-Register f. PortB
                                           ; dadurch sind Pullups an Port an
										   
	
								  
    ldi tmp, 255 
	out DDRC, tmp
	out PortC, tmp
					  
	
	; Timer Register werden belegt
    ; Timer 1
	in  tmp, TCCR1A
	ldi tmp,  (1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(1<<WGM10);
	out TCCR1A, tmp
	in  tmp, TCCR1B
	ldi tmp,  (1<<WGM12)|(1<<CS12)|(0<<CS11)|(0<<CS10)             ;Vorteiler ist 256
	out TCCR1B, tmp
    ; Timer 0
    in  tmp, TCCR0
	ldi tmp,(1<<CS02) | (1<<CS01)    ;Externe Clock, fallende Flanke
    out TCCR0,tmp   				 ;Register TCCR0 ist für die Clock
     in  tmp, MCUCR                 ;MCU Control Register einlesen
	 ldi tmp, (1<<ISC11)|(1<<ISC01) ;Interrupt Sense Control
	 out MCUCR, tmp					;für INT0 und INT1 auf fallende Flanke
     in  tmp, GICR                  ;General Interrupt Control Register einlesen
	 ldi tmp, (1<<INT2)|(1<<INT1)|(1<<INT0)	;Externe Interrupts 0, 1 und 2 an
     out GICR, tmp
     in tmp, TIMSK                  ;Timer Interrupt Mask Register einlesen
	 ldi tmp, (1<<TOIE1)			;Timer 1 Overflow IR an
     out TIMSK, tmp
	 sei      						;Interrupts allgemein zulassen
	 ldi compare_value, 40         ;PWM erst mal auf 50%
	 ldi tmp, 50
	 mov compare_value_M1, tmp
	 ldi reload, 39                 ;T1 Overflow erfolgt nach 217 * 256 * 62,5 ns
	 								;-> Interrupt alle 3,427 ms
	 ldi softcounter, 144			;-> für 2 Hz Samplerate nur alle 144 Interrupts
									;   Zähler auslesen und zurücksetzen
     ldi pulseMotor2, 0
	 out TCNT1L, reload
	 sbi PortD, Taster4				;erst mal eine 1 auf die Taster
     sbi PortD, Taster6				;damit die fallende Flanke 
	 								;den IR auslöst.
     sbi PortB, Pulse1	
	 sbi PortB, Pulse2
	 sbi PortB, Richtung1	
	 sbi PortB, Richtung2
	 sbi DDRA,clk              	;clk Pin als Ausgang
     sbi DDRA,richtung			;richtung Pin als Ausgang
     sbi DDRA,strom				;strom Pin als Ausgang
     sbi PORTA,clk				;clk Bit setzen
     cbi PORTA,richtung			;Richtung vorgeben
     sbi PORTA,strom			;Richtung vorgeben
	 ldi sollwert, 20
    
 ;------------------------------------------------------
 ;   HAUPTSCHLEIFE
 ;------------------------------------------------------
 Hauptschleife: 
     sbis PINA, PA0
	 call change_left
	 sbis PINA, PA1
	 call change_dir
	 sbis PINA, PA2
	 call change_right
	 
     rjmp Hauptschleife             ; immer wiederholen 
 Ende:  
        rjmp Ende
;------------------------------------------------------
 ;   ISR Extern0
 ;------------------------------------------------------
 EXTERN0:
	 ; Erst mal alles auf den Stack
	 PUSH tmp		;benutzte Register speichern
	 IN tmp, SREG	;Statusregister retten
     PUSH tmp		;
     
     ;Hier kommt unsere eigentliche Bearbeitung
	 ;
	 warten 1		;1 ms warten, da Taster prellt
	 
     ;Richtung umkehren
	 sbi PortB, Richtung1	
	 sbi PortB, Richtung2
	 warten10msMalX 40
	 ;Kurve einleiten
	 cbi PortB, Richtung2
	 warten10msMalX 20
	 ;und wieder gerade
	 cbi PortB, Richtung1
     
	 in  tmp, GIFR 		 		 
     ldi tmp, (1<<INTF0)	    ;durch Prellen des Tasters wurde schon 
	 out GIFR, tmp 				;ein neuer Interrrupt getriggert
								;manuelles setzen des Flags verhindert
								;eine erneute Ausführung der Routine
								;nach dem Rücksprung
             
	 ; Jetzt Register vom Stack wiederholen  	 
     POP tmp		;Statusregister wiederherstellen
	 OUT SREG, tmp	;
	 POP tmp		;benutzte Register wiederherstellen
     RETI 			;Rücksprung
 ;------------------------------------------------------
 ;   ISR Extern1
 ;------------------------------------------------------
 EXTERN1:
	 ; Erst mal alles auf den Stack
	 PUSH tmp		;benutzte Register speichern
	 IN tmp, SREG	;Statusregister retten
     PUSH tmp		;
     
     ;Hier kommt unsere eigentliche Bearbeitung
	 warten 1		;1 ms warten, da Taster prellt
	 ;Richtung umkehren
	 sbi PortB, Richtung1	
	 sbi PortB, Richtung2
	 warten10msMalX 40
	 ;Kurve einleiten
	 cbi PortB, Richtung1
	 warten10msMalX 20
	 ;und wieder gerade
	 cbi PortB, Richtung2
	 	  		 		 
     in  tmp, GIFR
     ldi tmp, (1<<INTF1)	    ;durch Prellen des Tasters wurde schon 
	 out GIFR, tmp 				;ein neuer Interrrupt getriggert
								;manuelles setzen des Flags verhindert
								;eine erneute Ausführung der Routine
								;nach dem Rücksprung
             
	 ; Jetzt Register vom Stack wiederholen  	 
     POP tmp		;Statusregister wiederherstellen
	 OUT SREG, tmp	;
	 POP tmp		;benutzte Register wiederherstellen
     RETI 			;Rücksprung
 ;------------------------------------------------------
 ;   ISR Extern2
 ;------------------------------------------------------
 EXTERN2:
	 ; Erst mal alles auf den Stack
	 PUSH tmp		;benutzte Register speichern
	 IN tmp, SREG	;Statusregister retten
     PUSH tmp		;
     
     ;Hier kommt unsere eigentliche Bearbeitung
	 inc pulseMotor2 
             
	 ; Jetzt Register vom Stack wiederholen  	 
     POP tmp		;Statusregister wiederherstellen
	 OUT SREG, tmp	;
	 POP tmp		;benutzte Register wiederherstellen
     RETI 			;Rücksprung
 ;------------------------------------------------------
 ;   ISR Timer1 Overflow
 ;------------------------------------------------------
 Timer1OVF:
     dec softcounter
	 brne go_back
     ; Erst mal alles auf den Stack
	 PUSH tmp		;benutzte Register speichern
	 IN tmp, SREG	;Statusregister retten
     PUSH tmp		;
     
     ;Hier kommt unsere eigentliche Bearbeitung
	 mov tmp, pulseMotor2          
	 call regelung_M2              
	 com tmp           ;Zählerstand auf
	 out PortC, tmp    ;LEDs ausgeben
     
	 ldi tmp, 0
	 out TCNT2, tmp
	 out TCNT0, tmp
	 ldi pulseMotor2, 0
	 out TCNT1L, reload
	 ldi softcounter, 144
		 
	 	  		 		            
	 ; Jetzt Register vom Stack wiederholen  	 
     POP tmp		;Statusregister wiederherstellen
	 OUT SREG, tmp	;
	 POP tmp		;benutzte Register wiederherstellen
go_back:
     RETI 			;Rücksprung
 ;------------------------------------------------------
 ;   Unterprogramm Regelung Motor 2 nach Sollwert
 ;------------------------------------------------------
regelung_M2:
    
	push tmp
	
	mov sollwert_M1, pulseMotor2	;aktuelle Pulse sind Sollwert für Motor1
	in pulseMotor1, TCNT0			;pulse für Motor1 festhalten
	clc
	cp sollwert, pulseMotor2
	brne checkDirection
	call regelung_M1
	pop tmp
	ret
 checkDirection:
    brcs langsamer	;Carry gesetzt, wenn pulseMotor2 > Sollwert
 schneller:
    mov calc, sollwert
    sub calc, pulseMotor2			;Pulse vom Sollwert abziehen
	mov tmp, compare_value			;schauen, ob Maximaldrehzahl schon erreicht
	clc
	add tmp, calc					;Regelabweichung addieren
	brcs back						;größer 255
	mov calc, tmp                   ;Ergebnis der Addition in calc 				
	mov compare_value, calc		
	out OCR1AL, compare_value		;compare Wert schreiben
	call regelung_M1
	pop tmp
	ret
 langsamer:
    mov calc, pulseMotor2
    sub calc, sollwert				;Sollwert von Pulsen abziehen
	mov tmp, compare_value			;schauen, ob Minimaldrehzahl schon erreicht
	sub tmp, calc					;Regelabweichung subtrahieren
	mov calc, tmp                   ;Ergebnis der Subtraktion in calc 
    ldi tmp, 55
	clc								;carry löschen
    cp calc, tmp					;schauen, ob calc (eigentlich neuer compare_value)					
	brcs back						;kleiner 55
    mov compare_value, calc         ;wenn nicht, übernehmen		
	out OCR1AL, compare_value		;compare Wert schreiben
 back:
    call regelung_M1
    pop tmp
    ret
 ;------------------------------------------------------
 ;   Unterprogramm Regelung Motor 1 nach Motor 2
 ;------------------------------------------------------
 regelung_M1:
    
	push tmp
	clc
	
	cp sollwert_M1, pulseMotor1
	brne checkDirection_M1
	pop tmp
	ret
 checkDirection_M1:
    brcs langsamer_M1	                 ;Carry gesetzt, wenn pulseMotor2 > Sollwert
 schneller_M1:
    mov calc, sollwert_M1
    sub calc, pulseMotor1			;Pulse vom Sollwert abziehen
	mov tmp, compare_value_M1			;schauen, ob Maximaldrehzahl schon erreicht
	clc
	add tmp, calc					;Regelabweichung addieren
	brcs back_M1						;größer 255
	mov calc, tmp                   ;Ergebnis der Addition in calc 				
	mov compare_value_M1, calc
	out OCR1BL, compare_value_M1		;compare Wert schreiben
	pop tmp
	ret
 langsamer_M1:
    mov calc, pulseMotor1
    sub calc, sollwert_M1				;Sollwert von Pulsen abziehen
	mov tmp, compare_value_M1			;schauen, ob Minimaldrehzahl schon erreicht
	sub tmp, calc					;Regelabweichung subtrahieren
	mov calc, tmp                   ;Ergebnis der Subtraktion in calc 
    ldi tmp, 55
	clc								;carry löschen
    cp calc, tmp					;schauen, ob calc (eigentlich neuer compare_value)					
	brcs back_M1						;kleiner 55
    mov compare_value_M1, calc         ;wenn nicht, übernehmen
	out OCR1BL, compare_value_M1		;compare Wert schreiben
 back_M1:
	pop tmp	
    ret
change_left:
      call step
     ;Richtung umkehren
	 cbi PortB, Richtung1	
	 cbi PortB, Richtung2
	 warten10msMalX 20
	 ;Kurve einleiten
	 sbi PortB, Richtung2
	 warten10msMalX 10
	 ;und wieder gerade
	 sbi PortB, Richtung1
	 ret
change_right:
     call step
     cbi PortB, Richtung1	
	 cbi PortB, Richtung2
	 warten10msMalX 20
	 ;Kurve einleiten
	 sbi PortB, Richtung1
	 warten10msMalX 10
	 ;und wieder gerade
	 sbi PortB, Richtung2
	 ret
change_dir:
     call step
     ;Richtung umkehren
	 cbi PortB, Richtung1	
	 cbi PortB, Richtung2
	 ret
step:
     sbis PORTA,CLK	     ;prüfe, ob CLK gesetzt ist
     rjmp aus	         ;dann überspringe diese Zeile
     cbi PORTA,CLK	     ;und schalte CLK ein
	 warten10msMalX 10
     ret	
aus:
     sbi PORTA,CLK	      ;CLK war gesetzt -> ausschalten
	 warten10msMalX 10
     ret
 danke schon im Vorraus,
Lesezeichen