Hallo,
ich bin grade am Programmieren des ATMega32.
Mein Programm soll folgendes erfüllen:
1.der Roboter soll gerade fahren
2. und wenn er gegen die taster vorne fährt sich ein bisschen dreht
Bei mir ist das Problem, dass er am Anfang grade aus fährt und wenn der
Roboter gegen was fährt auf einmal rückwärts fährt
damit ihr euch das angucken könnt, ist hier der Programmiercode:
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,
mit freundlichen Grüßen, technik97