- 3D-Druck Einstieg und Tipps         
Seite 2 von 6 ErsteErste 1234 ... LetzteLetzte
Ergebnis 11 bis 20 von 53

Thema: Assembler lernen

  1. #11
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    Anzeige

    Praxistest und DIY Projekte
    Hi,

    Zitat Zitat von HeSt
    ... frage: wie erzeuge ich interrupts an den eingängen? int0 oder pinchange? die entsprechenden pinb anklicken (aktiv setzen) bringt nichts ...
    ? ? ? Reale Interrupts im Programm oder im Simulator? Im Simulator hatte ich das nie hinbekommen; das hatte ich dann aufgegeben und lieber gleich im/mit Controller gemacht.

    Im Ablauf: 1) ISR (Interrupt Service Routine) schreiben. 2) Interrupt-Initialisierungsroutine schreiben. 2) Interrupt Vector Tabelle schreiben. 3) Port/Pin richtig initialisieren (noch immer Software). 4) Freuen, dass der Interrupt die richtige Aktion auslöst.
    Ciao sagt der JoeamBerg

  2. #12
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Soweit ich mich noch erinnere war das gar nicht so schwer einen Interrrupt auszulösen. Ist aber doch schon eine ganze Zeit her. Zur Not, wenn sonst nichts geht, könnte man auch die Interrupt flags direkt setzen. Wenn man ein spezielle Signal braucht gibt es noch einen externen Stimulus, ist aber auch nicht ganz einfach.

  3. #13
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    freunde,
    verzeiht einem ungeduldigen alten lehrling!
    ich rede immer noch vom avr, also vom simulator.
    der interrupt lässt sich übrigens schön auslösen, in dem man - so wie ich ja probiert habe - das pinb port bit auf ein setzt.
    allerdings muss man dann 2x die f11 taste drücken!! erst dann greift der interrupt und springt in die i-routine.

    so, und nun hab ich ein problem mit meinem programm, das ich nicht verstehe:
    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 - verhält sich also wie ein reset!!!
    wie das ???
    kann mir das einer erklären?
    was mache ich falsch bzw. wo liegt der hund in meinem gedankengang?

  4. #14
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    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.
    Ciao sagt der JoeamBerg

  5. #15
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Das SREG muß man selber retten. In der Regel ist das der Erste befehl nach dem RJMP in der Vektor tabelle.

    Es spricht nicht viel gegen rcall in der ISR.

    Eine Ursache für das Problem könnte ein nicht initialisierter Stack sein. Wenn der Stack noch irgendwo im Nirwana ist, dann kann der Rücksprung auch schon mal nach 0000 gehen.

  6. #16
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    danke euch beiden für die antworten!

    ich rufe aus der ISR deshalb eine SR auf, weil ich diese auch aus anderen SRs aufrufe - ich sie also mehrfach verwende.
    und es sollte kein problem dadurch geben - gibt es auch nicht - siehe weiter unten.

    der tip mit dem stack war gut!
    ich hatte die initialisierung irgendwo abgekupfert und die dürfte wohl nicht für den tiny 13 gedacht sein ...
    nach dem init stand die stapeladresse des SPL auf 0 !!
    ich hab die stack initialisierung mal raus genommen und siehe da, zumindest der simulator setzt die richtige größe (endadresse) ein.
    habe dann sicherheitshlaber das richtige init eingesetzt.
    habe dann weiter getestet - nun läufts richtig!!
    also war das SPL das problem.

    wie poste ich meinen code?
    aber das hat sich ja nun erübrigt oder?

    übrigens danke für den deinen!
    muss mich erst einlesen und verstehen!
    hab meinen servotester mit einem 555er gemacht.
    funktioniert auch tadellos.

  7. #17
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    Zitat Zitat von HeSt
    ... wie poste ich meinen code?
    aber das hat sich ja nun erübrigt oder? ...
    Code posten:
    Button [C ode] drücken ( danach steht dort [C ode*] ) ,
    jetzt den Code eingeben (z.B. copy und paste)
    Button [C ode*] drücken.

    Oder: Code eingeben, markieren und danach den Button [C ode] drücken.
    Anmerkung: Zwischen "C" und "o" muss hier im Text ein Zwischenraum stehen, damit die Schaltfunktion für den Code (an dieser Textstelle im Posting) nicht aktiviert wird.

    Deinen Code zu lesen hat sich ja nun erübrigt. Obwohl - wär ja mal interessant . . . . .

    Zitat Zitat von HeSt
    ... übrigens danke für den deinen!
    muss mich erst einlesen und verstehen! ...
    Ich hatte gerade festgestellt, dass mein Beispiel total schlecht ist. Dieses hier ist vermutlich etwas besser: Stack ist initialisiert, Stackpointer wird in der ISR gesichert und so. Man entwickelt sich halt mit der Zeit *ggggg*.

    Code:
    /* =================================================================================
      Sicherung 20dez07 1732 nach Datei ..A1..\minitest\minitest_x10.asm
     ===================================================================================
    ..............
     ===================================================================================
                                                                                      */
    /* ============================================================================== */
    ; Deklarationen für den Praeprozessor und Konstanten (s.auch oben Speicherbelegung)
    
    #include <m168def.inc>
    
    #define	a	r16	;Kurzbezeichung für Allzweckregister r16
    #define	ac	r17	;Kurzbezeichung für ISR-Allzweckregister r17
    ;===================================================================================
    /* Interrupthandler-Tabelle 
    	Address Code	Labels		; Comments			*/
    .org  0x0000  rjmp  RESET	;Reset Handler, power-on, brown-out, watchdog
    /*.org  0x0001  rjmp  xt_int0	; EXT_INTO  IRQO Handler
    .org  0x0002  reti	; PCINTO    PCINTO Handler
    .org  0x0003  reti	; TIMO_OVF	;Timer0 Overflow Handler
    .org  0x0004  reti	; EE_RDY	;EEPROM Ready Handler
    .org  0x0005  reti	; PITAL_COMP	;Analog Comparator Handler
    .org  0x0006  reti	; TIMO_COMPA	;Timer0 CompareA Handler
    .org  0x0007  reti	; TIMO_COMPE	;Timer0 CompareE Handler
    .org  0x0008  reti	; WATCHDOG	;Watchdog Interrupt Handler
    .org  0x0009  reti	; ADC		;ADC Conversion Handler
                                                                                      */
    ;===================================================================================
    ; Hauptprogramm
    ;===================================================================================
    ;
    RESET:		;=== Generelle Initialisierung
    		; Zuerst RAMEND und Stack definieren;
    	ldi	a,RAMEND	;Ram Ende des tiny13
    	out	SPL,a		;Stack Pointer tiny13 setzen
    anfang:		;=== Nur ein Dummy-Hauptprogramm
    	rcall  	init_mc		;Initialisiere den Mikrocontroller
    	rcall	ini_xti0	;Initialisiere die ISR für external Interrupt
    	sei			; .. und Interrupts allgemein zulassen
    a2:
    	rcall	tiw		;Tu irgend etwas
    	rjmp	a2
    ;		
    ;===================================================================================
    ; Prozeduren
    ;===================================================================================
    ;
    tiw:	;=== tuirgendwas ... ein bisschen code muss ja abgearbeitet werden
    	push	a
    	in	a,SREG
    	push	a
    	push	ac		;AUCH das ISR-Allzweckbyte - auf alle Fälle
    tiw_pop:
    	pop	ac
    	pop	a
    	out	SREG,a
    	pop	a
    	ret		;=====----->>>>>
    ;
    ;===================================================================================
    ; Initialisierungen für µC und ISR
    ;===================================================================================
    ;
    init_mc:	;=== Initialisiere Mikrocontroller
    		;ALLE Register initialisieren hier := pull-ups einschalten
    	ldi	a,0b00111100	;
    	out	ddrb,a		;Datenrichtung "Ausgabe" für alle ports
    	ldi	a,0b00000000
    	out	portb,a		;  und alle ports ausschalten = low = sink
    	ret		;=====----->>>>>
    ;
    ini_xti0:	;=== Initialisiere external Interrupt
    ;
    				;(1<<ISC01 | 1<<ISC00)
    	ldi	a,0b00000011	;Init. extern. Interrupt0 auf rising edge
    	out	MCUCR,a		;   d.h. MCUCR ISC00,01 auf 1 (doc2535,S 55)
    	ldi	a,0b01000000	;(1<<INT0)
    	out	GIMSK,a		;  und erlaube diese I´s in GIMSK
    	ret		;=====----->>>>>
    ;
    ;===================================================================================
    ; Interrupt-Service-Routine	#######>>>>> 
    ;===================================================================================
    ;
    xt_int0:	;=== Markiere Arbeit dieser ISR
    	push	a
    	in	a,SREG
    	push	a
    	ldi	a,0b00001000	;Bit3 (PB3) einschalten
    	out	portb,a
    int0_pop:
    	pop	a
    	out	SREG,a
    	pop	a
    	reti		;=====----->>>>>
    ;
    ;===================================================================================
    ; Ende des Quellcodes
    ;===================================================================================
    Ciao sagt der JoeamBerg

  8. #18
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    hallo joe,
    entschuldige, gibts einen "C" oder "C ode" button?
    ich hab hier ein kleines fensterchen "Kurz Antwort" mit 4 buttons drunter, aber keiner davon entspricht dem genannten.
    auch nicht im header oder unter jeder antwort werde ich fündig.
    tut mir leid, da stehe ich auf der leitung!
    gib mir nen schubbs zur seite !!

  9. #19
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    1) Du kannst in das Fenster [Kurze Antwort] schreiben. Da gibts den Button (noch) nicht. Wenn Du dann auf [Vorschau] drückst - ahhhhhhhh .
    2) Wenn Du gleich auf [zitat], rechts oben, oder [antwort erstellen], links unten, drückst - dann kommt auch das volle Programm . . . . .
    In beiden Fällen kommt der verschwundene C ode Button zum Vorschein . Nicht zum Lesen gedacht: Die dämliche Organisation der Computer ist so komplex, dass man zum an sich unerwünschten "mal den Button drücken, mal den hier versuchen" animiert wird. Und sich dann wundert, wenn man in der Wüste/im Wald landet.

    Hier im Forum kann eine halbe Stunde in der guten FAQ-Stube, Schaltfläche siehe oben-mitte, nützlich sein. Man muss ja nicht alles lesen - Hauptsache, man weiss wo man es findet.

    Uuuups - war das DER Schubs? Viel Erfolg.
    Ciao sagt der JoeamBerg

  10. #20
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    danke für den schubs !!
    er hat geholfen

    nun mein code, denn erfunktioniert im simulator 1a (da werden die interrupts per mausklick im PINB aktiviert), aber leider nicht mit dem tiny13 .

    Code:
    ;*******************************************************************
    ;* 
    ;* Programm: GTRiegel
    ;* 
    ;* Version: 1.0
    ;* 
    ;* 
    ;* Portzuordnung:
    ;* PB0	< Schalter Tor zu		PinChange Interrupt
    ;* PB1	< Impuls Tor auf/zu		INT0 Interrupt
    ;* PB2	< Sensor Riegel offen/zu	3 Zustände möglich!!! (ADC)
    ;* PB3	> Riegel auf
    ;* PB4	> Riegel zu
    ;* PB5	> Impuls zur Torelektronik auf/zu
    ;*
    ;* PB0 und PB1 sind Interrupt gesteuerte Eingänge                                                                ;* 
    ;*******************************************************************
    ; Definitionen
    ;*******************************************************************
    
    #include "tn13def.inc"
    
    .cseg
    .org	0x000		; Interrupt Vektoren	
    	rjmp MAIN	; Hauptprogrammroutine (Reset)
    	rjmp IMPLS	; Interrupt0
    	rjmp CLSLATCH	; PinChangeInterrupt Tor zu
    	rjmp TMROVF	; TimerOverFlow für Warteschleife
    	rjmp MAIN	; Hauptprogrammroutine
    	rjmp MAIN	; Hauptprogrammroutine
    	rjmp MAIN	; Hauptprogrammroutine
    	rjmp MAIN	; Hauptprogrammroutine
    	rjmp MAIN	; Hauptprogrammroutine
    	rjmp MAIN	; Hauptprogrammroutine
    
    .def	TIM1 = R16	; Timer 1 für Wartezeit
    .def	TIM2 = R17	; Timer 2 für Wartezeit
    .def	TSEC = R18	; Sekundenregister für Zeitügabe
    .def	SCNT = R19	; Sekundenregister für Timer
    .def	TEMP = R20	; dient für diverse Operationen
    .def	SAVR = R21	; dient zum Sichern des SREG
    .def	ADCV = R22	; enthält Wert von ADCH nach AD-Wandlung
    .def	DIMI = R23	; "Door In Motion" Indikator
    			; dient zur Abfrage bei weiterem Impuls
    			; während Tor in Bewegung
    			; Bit Bedeutungen:
    			; Bit2: 1=Tor während Bewegung gestoppt
    			; Bit1: 0=Bewegung war auf, 1=war zu
    			; Bit0: 1=in Bewegung, 0=abgeschlossen
     
     
     
    ;*******************************************************************
     MAIN:
    ;*******************************************************************
    ; Generelle Initialisierungen
    ;-------------------------------------------------------------------
    ; Allgemeine Interrupts verhindern
    	cli
    
    ; Arbeitsregister löschen
    	clr	ADCV
    	clr	DIMI
    
    ; Stack anlegen
    	ldi	temp,LOW(RAMEND)
    	out	SPL,temp
    
    ; Ports initialisieren
    	ldi	temp,0b00111000	; Register für DDRB in/out laden
    	out	DDRB,temp	; 0 1 2 Eingänge  3 4 5 Ausgänge
    	ldi	temp,0b00000010	; Register für PORTB PB1 laden
    	out	PORTB,temp	; PB1 PullUp,  Ausgänge low
    
    ; ADC initialisieren
    	ldi	temp,6		; Reg. für ADC prescaler laden
    	out	ADCSRA,temp	; 6 (divider 64) sind ca 18kHz
    	ldi	temp,1		; Reg. für ADMUX PB2 laden
    	out	ADMUX,temp	; ADMUX setzen
    
    ; Wait-Timer setzen
    	ldi	temp,3		; Vorteiler /64
    	out	TCCR0B,temp
    
    ; Interrupt Register setzen
    	ldi	temp,0b00110001	; 0bxxxxxxx1 INT0 jede Level-
    				; änderung löst Interrupt aus
    	out	MCUCR,temp	; 0bxx11xxxx Sleep-Mode auf
    				; PowerDown setzen
    	ldi	temp,0b01100000	; GIMSK Interrupt Mask setzen
    	out	GIMSK,temp	; Int0 und PinChange enable
    	ldi	temp,1		; PinChange auf PB0 beschränken
    	out	PCMSK,temp	
    
    ; Initialisierung beendet > enter SLEEP-Modus
    	rjmp	pwrdwn		; dann power down
    
     
    ;*******************************************************************
    ;******************** START INTERRUPT ROUTINEN *********************
    ;*******************************************************************
    
    ;*******************************************************************
     IMPLS:		; OK
    ;-------------------------------------------------------------------
    ; Interruptroutine (INT0): 
    ; Diese I-Routine besitz nur den RJUMP Befehl zur Subroutine, da 
    ; diese auch aus dem Programmablauf aufgerufen werden können muss. 
    ; SREG braucht nicht gesichert zu werden, da keine Rückkehr 
    ; erfolgt (rjmp).
    ;*******************************************************************
    	rjmp	impuls
    	reti
    
    ;*******************************************************************
     CLSLATCH:		; OK
    ;-------------------------------------------------------------------
    ; Diese Interruptroutine wird durch den PINchange (Tor zu) an PB0
    ; ausgelöst und schließt den Riegel
    ;-------------------------------------------------------------------
    	in	savr,SREG 
    	cli			; weitere Interrupts verhindern
    	clr	dimi		; Tor in (Soll)Endstellung ZU
    	sbi	portb,4		; PB 4 ein = Riegel schließen
    WCLSLATCH:
    	rcall	readadc
    	sbrs	adcv,0		; Bit1=1 = Riegel geschlossen
    	rjmp	wclslatch	; neue Abfrage bis geschlossen
    	cbi	portb,4		; PB 4 aus 
    	rjmp	pwrdwn
    	reti
    
    ;*******************************************************************
     TMROVF:		; OK
    ;-------------------------------------------------------------------
    ; Diese Interruptroutine wird durch den TimerOVF Interrupt
    ; aufgerufen
    ;-------------------------------------------------------------------
    	in	savr,SREG 
    	clr	tim1 
    	out	TCNT0,tim1	; Timer zurücksetzen
    	inc	tim2
    	cpi	tim2,75		; 75 cylces = ca. Sekunde
    	brlo	tmrovfe
    	clr	tim2
    	inc	scnt		; Sekundenzähler um 1 erhöhen
     TMROVFE:
    	out	SREG,savr
    	reti
    
    ;******************** ENDE INTERRUPTROUTINEN ***********************
    
    
     
    ;*******************************************************************
    ;*********************** START SUB ROUTINEN ************************
    ;*******************************************************************
    
    ;*******************************************************************
     IMPULS:		; OK
    ;-------------------------------------------------------------------
    ; Fragt Status von Tor und Riegel ab und führt entsprechende
    ; Routinen aus
    ;-------------------------------------------------------------------
    	cli			; weitere Interrupts verhindern
    	cpi	dimi,0		; DIMI=0, Torbewegung abgeschlossen
    	breq	normrun		; wenn ja, normaler Ablauf
    	sbrc	dimi,2		; Bit2=0 Tor in Bewegung > skip
    	rjmp	revers
    	rcall	doorimp		; Bewegung stoppen
    	sbr	dimi,2		; Tor in Bewegung gestoppt
    	rjmp	pwrdwn
    
    REVERS:				; letzte Torrichtung umdrehen
    	sbrs	dimi,1		; Tor Richtung war ZU > skip 
    	rcall	clsdoor		; mit Schließen des Riegels
    	rcall	doorimp		; Tor öffnen
    	cbr	dimi,1		; Torrichtung = AUF
    	ldi	tsec,30		; Wartezeit laden
    	rcall	wait
    	clr	dimi		; wenn alles OK, DIMI = 0 
    	rjmp	pwrdwn	
    
     NORMRUN:	
    	sbis	pinb,2		; Abfrage Riegel zu? > skip
    	rjmp	clsdoor		; Tor + Riegel schließen
    	rjmp	opndoor		; Riegel + Tor öffnen
    	ret
    
    ;*******************************************************************
     READADC:		; OK	
    ;-------------------------------------------------------------------
    ; Liest den A/D Wandler an PB2 aus	 ADC 10 Bit Messung
    ; Da es sich hier um keine digitale „Spannungsmessung“ handelt 
    ; sondern lediglich um eine „Statusabfrage“ reicht hierzu nur die
    ; Abfrage des Hi-Byte (ADCH):
    ;   0V = Riegel offen		ADCH = 0
    ;   2V = Riegel „unterwegs“	ADCH = 1
    ;   5V = Riegel geschlossen	ADCH = 3 (oder Abfrage dec. >1)
    ; Die Messung muss doppelt erfolgen ansonsten wird die vorherige
    ; Messung eingelesen – Eigenheit des Tiny13
    ;-------------------------------------------------------------------
    	sbi	ADCSRA,ADEN	; ADC ENable
    	sbi	ADCSRA,ADSC	; ADC Start Conversion
    
     WREADADC1:	; Schleife bis Messung
    	sbic	ADCSRA,ADSC	; abgeschlossen = ADSC=0
    	rjmp	wreadadc1
    	sbi	ADCSRA,ADSC	; ADC Messung 2tes Mal starten
    
     
     
    WREADADC2:
    	sbic	ADCSRA,ADSC	; warten bis ADSC = 0 
    	rjmp	wreadadc2
    	in	temp,ADCL	; lowbyte einlesen
    	in	adcv,ADCH	; highbyte einlesen
    	cbi	ADCSRA,ADEN	; ADC ausschalten
    	ret
    
    ;*******************************************************************
     CLSDOOR:		; OK
    ;-------------------------------------------------------------------
    ; Schickt Tor Impuls zum Schließen, setzt DIMI
    ;-------------------------------------------------------------------
    	rcall	doorimp
    	sbr	dimi,1		; Bit1=1 = Torbewegung ZU
    	rjmp	pwrdwn		; sleep bis Interrupt „Tor zu“ (PB0)
    	ret
    
    ;*******************************************************************
     OPNDOOR:		; OK
    ;-------------------------------------------------------------------
    ; Öffnet Riegel und Tor
    ;-------------------------------------------------------------------
    	sbi	portb,3		; PB 3 ein = Riegel öffnen
    
     WOPEN:
    	rcall	readadc
    	nop
    	cpi	adcv,0		; compare (0=offen)
    	brge	wopen		; neue abfrage bis offen
    	cbi	portb,3		; PB 3 aus 
    	rcall doorimp
    	ldi	dimi,1		; Torbewegung AUF
    	ldi	tsec,30		; Wartezeit von 30 Sek. für Wait
    	rcall	wait		; Warteschleife
    	clr	dimi		; DIM Indikator löschen
    	rjmp	pwrdwn
    	ret
    
    ;*******************************************************************
     DOORIMP:		; OK
    ;-------------------------------------------------------------------
    ; schickt einen Impuls von etwa 1 Sekunde zur Torelektronik
    ;-------------------------------------------------------------------
    	ldi	tsec,1		; Zeit für Impulsspreizung in Sek
    	sbi	portb,5		; PB 5 ein = Impuls Tor auf
    	rcall	wait		; Impulsspreizung
    	cbi	portb,5		; PB 5 aus
    	ret
    
     
    ;*******************************************************************
     WAIT:		; OK
    ;-------------------------------------------------------------------
    ; Warteschleife für diverse Zeitverzögerungen
    ; Wartezeit wird von aufrufender Routine in TSEC übergeben
    ; Es wird der PinChange Interrupt kurzfristig unterdrückt, da beim
    ; Öffnen des Tores ungewollt ein PCI ausgelöst wird. 
    ; Der PCI wird vor dem enable wieder gelöscht, damit dieser nicht 
    ; nach der generellen Freigabe der Interrupts ausgeführt wird.
    ;-------------------------------------------------------------------
    	in	temp,GIMSK
    	cbr	temp,5
    	out	GIMSK,temp	; PCI disable
    	clr	scnt
    	ldi	temp,2
    	out	TIMSK0,temp	; Timer Interrupt freigeben
    				; Timer läuft .....
    	sei
     LOOP:
    	cp	scnt,tsec	; Sekunden abgelaufen?
    	brlo	loop
    	clr	temp
    	out	TIMSK0,temp	; Timer Interrupt sperren, restliche
    				; Interrupts bleiben ein
    	in	temp,GIFR
    	cbr	temp,5
    	out	GIFR,temp	; PCI löschen
    	in	temp,GIMSK
    	sbr	temp,5
    	out	GIMSK,temp	; PCI enable
    	clr	scnt
    	ret
    
    ;******************************************************************
     PWRDWN:		; OK
    ;-------------------------------------------------------------------
    ; Beendet alle Funktionen, gibt die Interrupts frei und schaltet ab
    ; Ein Interrupt an PB1 (INT0) oder an PB0 (PinChange) aktiviert 
    ; den Processor wieder 
    ;-------------------------------------------------------------------
    	sei			; alle Interrupts frei geben
    	sleep			; Power Down, warten auf Interrupts
    
    ;************************ ENDE SUBROUTINEN *************************
    
    .EXIT
    wenn ich ihn in den tiny lade (mittels platine und programm vom franzis lernpaket) scheint er sofort in die "clslatch" routine zu laufen, denn PB4 ist aktiv. wenn ich das signal an PB2 dann gegen Vcc bringe schaltet er ab.
    aber - und das ist komisch, kein interrupt bringt ihn aus dem schlaf oder aus der schleife, die ich testweise statt der letzten zeile "pwrdwn" in MAIN probiert habe:

    Kreis:
    sei
    nop
    rjmp kreis

    hast du eine idee??
    wo hab ich meinen gedankenfehler?

    schon vorab danke für deine mühe und geduld mit mir !!

Seite 2 von 6 ErsteErste 1234 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress