Zitat Zitat von HeSt
... ich rede immer noch vom avr, also vom simulator ...
Vorsicht - "der avr" würde für mich eher nach dem realen Controller klingen als nach dem Simulator.

Zitat Zitat von HeSt
... problem mit meinem programm ...
1. interrupt routine (irr) wird aufgerufen (das SREG wird gesichert)
2. irr macht ein rcall auf eine subroutine (ist ja normal oder?)
3. in der subr gibts unter anderen befehlen 2 schleifen mit rjmp
4. wenn die subr dann auf das ret(urn) kommt, springt das programm nicht in die aufrufende irr zurück (war ja rcall) sondern auf @$0000 ...
Hmmm, das klingt seltsam, und es klingt nicht gut. Also - ich weiß nicht, ob ein rcall in einer ISR sinnig (oder möglich - oder erlaubt) ist - ich hatte das nie gemacht. Ich lebe unter der Philosophie, dass die ISR so schnell wie möglich abzuarbeiten ist.

Nur nebenbei: die ISR wird mit reti abgeschlossen: Return from Interrupt, aber das wird Dir sicher schon klar sein.

Ich habe mal einen funktionierenden Code hervorgeholt, den ich vor Jahrhunderten in Assembler geschrieben hatte und der noch immer in meinem tiny13 als potentionmeter-getriebener Servotester funktioniert. Vielleicht hilft Dir so ein Anschauungsmaterial. Ich muss dazusagen, dass das kein perfekter Code ist - also er hat nicht direkt Vorbildfunktion. Aber der hex-file läuft.

Code:
; >>> 
; Sicherung vom 21jan08, 13:46 nach Datei servo1_servoplatine-gut.asm
;===================================================================================
;========== Beachte: printout aus AVRStudio geht (nur) bis col 85 ==================
;* Target MCU        : ATtiny13
;* Target Hardware   : Servotester-Platine, Servo auf PB3, Poti auf PB4
;* Target cpu-frequ. : 9,6 MHz, interner Oszillator
;===================================================================================
;*Versionsgeschichte:
;====================
;x1599 21jan08 12ff Version für die "Servoplatine" adaptiert
;       dazu ISR+adc+servo1-x30-gut.asm abgeändert.
;
;* Aufgabenstellung
;* ISR zum Testen von einem Servo mit der Servotester-Platine
;	Servo über getrennte Leitung, max. 1 A, vom Labornetzteil versorgt
;	Portbelegung, Schaltung auszugsweise (übernomm. v. srv-adc+pwm-x29b.asm)
;
; Vcc(6V LNT) -----------------------------------------Vcc-Servo1
;                                                                 
; Vcc -----------tiny13-Vcc                                 
;         |                                                
;         |      tiny13-PB3=pin2----------------+---Signal-Servo1   
;         |                                     |               
;         |              + - - (poti1->ADC) - - +               
;         |              |                                      
;         |      tiny13-PB4--------+                           
;         |                        V                           
;         |                   +--------+                       
;         +-------------------+ 25klin +----+                  
;                             +--------+    |                  
;                                           |                  
; GND---------------------------------------+----------GND-Servo1
;             
;* ===============================================
; ######### Original war: ISR+adc+servo1-x30-gut.asm
;===================================================================================
; Speicherbelegung
;r14  low-Byte der ADC-Wandlung (lsb)
;r15  high-Byte der ADC-Wandlung: Beide ergeben einen Wert zwischen 0...1023
;r16 Mehrzweck, high-Byte in Pausen "pause_an", "pause_aus", "led_ende" u.ä.
;r17			low-Byte in Pausen, s.o.
;
;r18  --		--
;r19  --		--
;r20  --		--
;
;r21  Byte		Steuerbyte. Es werden nur Bits ausgewertet
;		"Rampe" an-aus, 1=Rampe an, bit 1 = Servo 1 , bit 5 = Servo 2
;		Übernahme Rampenwert, 1=Daten wurden noch nicht übernommen vom
;		Hauptprogramm in die ISR, 0=ISR hat Daten abgeholt und zwar
;			bit 2 = Servo 1 , bit 6 = Servo 2
;r22  1/2 Word lsb	Zeitwert Rampe aus auf-ab-Rechnerei im Hauptprogramm
;r23  1/2 Word msb zu r26
;r24  1/2 Word LSB	Zeitwert Rampe aus ADC/Poti im Hauptprogramm
;r25  1/2 Word MSB		wird vom r14/15 geholt und zurechtgerechnet
;
;r26  1/2 Word LSB	GESAMTDAUER Servoimpuls MUSS in r26/27 sein wegen sbiw
;r27  1/2 Word MSB	Zeitwert für GESAMTDAUER Servoimpuls, etwa 500 Takte ?
;
;r28  1/2 Word lsb	LSB RampenCOUNTER Servo1, wird in ISR runtergezählt
;r29  1/2 Word msb	MSB	  Counter stammt vom ADC
;r30  1/2 Word lsb	LSB Auf-ab-COUNTER Servo2, wird in ISR runtergezählt
;r31  1/2 Word msb	MSB
;
;===================================================================================

#include "tn13def.inc"

; Interrupthandler-Tabelle (aus ATTiny13_doc2535.pdf, Seite 42)
;	Address Code	Labels		; Comments
.org	0x0000	rjmp	anfang		; Reset Handler
;.org	0x0003	rjmp	isr_x13		;TIMO_OVF = Timer0 Overflow Handler

.org	0x0006	rjmp	isr_ctc		; IRS für Timer0 CompareA Handler
;
;===================================================================================
; Deklarationen für den Praeprozessor
; Konstanten		####### evtl. auch keine Konstanten definiert
;
#define	a	r16	;Kurzbezeichung für Allzweckregister r16
;
;	Anschlussbelegung, vgl. srv-adc+pwm-x29b.asm
#define servo1	3	;Servo 1 auf Port PB3
#define potiadc	2	;Poti 1 am Port PB4 geht auf ADC-Kanal 2
;
;Festwerte und div. Daten für adcdat etc ====>
#define	adcpsc	7	; =7 ==> Clock/128, 9,6 MHz werden 75 kHz, vgl. doc, S93
;#define adcdat	3	;Dummywert vom ADC   ###>>> "Nur" 8Bit-Wandlung ! ? ! 
#define msges	5000	;Gesamtzeit der Rampe: 5000 ISR-Zyklen sind 20 ms
#define mstest	500	;Test ergibt mit mstest 500 und tmprs 40: für 2,0 ms
			;  das heisst: 4 µs Interrupt-Abstand (Fehler +4%)
#define msmin	180	;Minimalwert für Rampe: 0,5 ms
#define	tmrprs	38	;Preset im Timer-Register (hoffentlich für CTC)
;
;===================================================================================
; Hauptprogramm
;===================================================================================
;
anfang:
	rcall  	mc_init		;Initialisiere den Mikrocontroller
	rcall	isr_ini		;Initialisiere die ISR
	rcall	adcinit		;ADC initialisieren
;
	sei			; .. Interrupts allgemein zulassen im Hauptprogramm

anfang2:
	rcall	adc_hol		;Hole Daten vom ADC in Register low=r14 + high=r15
;
	rjmp	anfang2
;		
;===================================================================================
; Prozeduren
;===================================================================================
;
adc_hol:	;=== Hole Daten vom ADC, wird erst NACH der Wandlung verlassen
				;Nach Wandlung sind die Werte in; L=r14,H=r15
	ldi	r16,potiadc	;Poti ist auf ADC-Kanal 2. >> Kanal 0 = Pin1=PB5,
				; K1(ADC1)=Pin7=PB2, K2=Pin3=PB4 und K3=Pin2=PB3
	rcall	rdadc		;ADC auslesen
	ret		;=====----->>>>>
;
rdadc:		;=== Hole Daten vom ADC in die Register low=r14 + high=r15
	out	admux,r16	;vgl.doc2535, S 79
	sbi	admux,adlar	;Result left adjusted ==> NUR 8-Bit-Wandlung
	sbi	adcsra,adsc	;Wandlung starten
adrdy:		;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
	sbic	adcsra,adsc	;Skip if bit is cleared => dann ADC fertig   
	rjmp	adrdy		; .. wenn nicht fertig, warten
adrdyb:
	sbic	adcsra,adsc	;Erst zweite Wandlung bringt korrektes Erbebnis,
	rjmp	adrdyb		;  vgl. doc2535, sonst könnte alter Wert da sein.
		;   Dies dann, ###===>>> nur WENN der Kanal umgeschaltet wurde.
;	in	r14,adcl	;Daten einlesen, zuerst Low-Byte - nicht bei adlar
	in	r15,adch	;vgl. oben ADMUX (out 3), ADSC
	ret		;=====----->>>>>
;
;===================================================================================
; Initialisierungprozeduren, für µC, ADC und Timer-ISR
;===================================================================================
;
mc_init:	;=== Initialisiere Mikrocontroller
		; PB0 (servo1) + PB3 (servo2) = Ausgang, PB4 (poti1) = ADC-Eingang
	ldi	r16,0b00001000	;Ausgang (1) auf PB3, Eingang (0) auf PB4
	out	ddrb,r16	;Datenrichtungsbits setzen, Port ist Ausgang
	ldi	r16,0b11100111	;Datenrichtungsbits setzen
	out	portb,r16	;  und initialisieren
	ret		;=====----->>>>>
;
adcinit:	;=== Initialisiere ADC und hole Daten
	ldi	a,adcpsc	;Setze adpsc0,1,2 => Clock/128, siehe define
	out	adcsra,a	;Lade prescaler ==>  75 kHZ, siehe define
	sbi	admux,potiadc	;Wandlung vom Kanal ADC2 = PB4 = potiadc
	sbi	admux,adlar	;Result left adjusted ==> NUR 8-Bit-Wandlung
	sbi	adcsra,aden	;AD en-able einschalten
	sbi	adcsra,adsc	;Wandlung zum Initialisieren starten
;
adrdy_in1:	;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
	sbic	adcsra,adsc	;Skip if bit is cleared => dann ADC fertig   
	rjmp	adrdy_in1		; .. wenn nicht fertig, warten
adrdy_in2:	;=== Warte bis ADC fertig ist ==> ZWEI Wandlngen durchführen
	sbic	adcsra,adsc	;Skip if bit is cleared => dann ADC fertig   
	rjmp	adrdy_in2		; .. wenn nicht fertig, warten
;
	ldi	r16,0b00000000	;Dummy-Muster
	mov	r14,r16		;Muster nach r14
	mov	r15,r16		;  .. und nach r15

	sbi	adcsra,aden	;AD en-able einschalten
	sbi	adcsra,adsc	;Wandlung zum Initialisieren starten

	ret		;=====----->>>>>
;
;
isr_ini:	;=== Initialisierung der ISR (war mal isrinit_x15)
;
;;Timer Register werden belegt
	ldi	a,(1<<wgm01)	;prescaler ist 1, waveform = CTC
	out	tccr0a,a	;Register TCCR0 ist für den Prescaler zuständig
	ldi	a,(1<<cs00)	;prescaler ist 1 => kein Prescaling, Abstand zum
	out	tccr0b,a	;  nächsten Interrupt bestimmt der
				;  CTC-Prescaler tmrprs
	ldi	a,(1<<ocie0a)	;Hier Interrupts nach CTC eingeschaltet
	out	timsk0,a	;Register TIMSK ist dafür zuständig 
	ldi	a,tmrprs	;Hier wird der Timer vorgeladen. Er läuft dann
	out 	TCNT0,a   	; .. tmrprs mal durch bevor ein Interrupt auftritt
	out	ocr0a,a		;Preset tmrprs in OCR0A
        			; .. Interrupts allgemein zulassen im Hauptprogramm
;	ret		;=====----->>>>>
;
;
;===================================================================================
; Interrupt-Service-Routine
;===================================================================================
;
;
isr_ctc:	;=== Immer wieder Veränderungen
;
	sbiw	r27:r26,1	;Pointer von 5000 runterzählen
				;  für EINEN Servoimpuls von 20 ms
	breq	i_neu		;  .. und Spezialfall "null" ==> Daten umschaufeln
				;  und Rampe einschalten. WENN keine neuen Daten da
				;  sind, dann alte Daten nehmen :(
;
; Jetzt wird nachgesehen, ob eine der Rampen ausgeschaltet werden muss. Das steht
; im Portbit ddrb
;
isr_nn:		;=== Zähler der ISR steht nicht auf Null
s1_pran:	;=== Servo1: Prüfe, ob Rampe ist an
	in	r20,portb
	sbrs	r20,servo1	;Ist Rampe von servo1 an?
	rjmp	i_raus		;Wenn Rampe nicht an ist, dann gleich raus
;
	sbiw	r29:r28,1	;Decrementiere Rampenwert
	brne	i_raus		;weiter, wenn noch nicht Null zu servo2
	cbi	portb,servo1	;  Sonst Lösche Rampe für Servo1
;
	rjmp	i_raus

	sbiw	r29:r28,1
	breq	i_neu
	rjmp	i_raus

i_neu:				;Daten neu in Register und port servo1 umschalten
	ldi	r28,low(msmin)
	ldi	r29,high(msmin)
;	mov	r17,r15		;Es ist adlar gesetzt, das ADCLH ist in r15
	ldi	r18,0
	add	r28,r15
	adc	r29,r18
				;Und ADC-Wert gleich nochmal draufaddieren
				;  aber nur die Hälfte
	clc			;Clear carry für anschliessende Division /2
	ror	r15		;
	add	r28,r15
	adc	r29,r18
;
	ldi	r26,low(msges)	;Loopgrenzen für Gesamtloop 20 msec
	ldi	r27,high(msges)
	sbi	portb,servo1	;  Und setze Rampe für Servo1. FERTIG
;
i_raus:
	reti		;=====----->>>>>
;
;===================================================================================
; Ende des Quellcodes
;===================================================================================
Vielleicht postest Du mal Deinen code? Auf jeden Fall mal viel Erfolg für Dich.