- 3D-Druck Einstieg und Tipps         
Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte
Ergebnis 41 bis 50 von 53

Thema: Assembler lernen

  1. #41
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Anzeige

    Powerstation Test
    Es stimmt, das die IO Register beim Reset neu initialieseirt werde, aber eines davon, MCUSR, enthält genau die Information wodurch der Reset ausgelöst wurde.

    Mit einigen Einschränkungen kann man also auch erkennen ob man ein Signal von der Resetleitung bekommen hat. Das geht natürlich nur für eher kurzr low Pulse, denn solange Reset low ist, läuf nichts. Außerdem werden wärend des Resets die anderen IO Ports alle hochohmig, was auch nicht immer paßt. Die Programmierung ist gerade für einen Anfänger alles andere als einfach. Zum Abfrage von Tastern oder Schaltern kann man oft mit relativ wenig externer schaltung auch so 2 oder 3 Tasten an einem Port abfragen. Beim Asuro wird dsa z.B. über den AD Wandler und Widerstände gemacht.

  2. #42
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    Hallo HeSt,

    Zitat Zitat von HeSt
    ... und ich hab leider kein programm mit dem ich fuses ändern kann ...
    Na ja, das stimmt nicht "in letzter Konsequenz". Das Programm LPmirkros setzt die fuses für die geforderte Umgebung, damit das Experimentierprogramm laufen kann. Das Ganze wird beim Laden des Bootloaders erledigt:

    ........................Bild hier  

    Dabei werden folgende fuses gesetzt (Du hast ja mit einem "jungfräulichen" ATtiny13 angefangen):

    ........................Bild hier  

    Das Testprogramm mit Bootloader sieht dann im Flash des t13 so aus:


    Code:
    :100000007FC1FFFFFFFFFFFFFFFFFFFFFFFFFFFFBE
    :10002000B99AB5D0AAD0D6D1CAD0302F313011F478
    :1000300004E6D9D0303119F4C2D0097108BB31318E
    :1000400021F4BDD00B71026007BB323131F400E006
    :1000500006BF03E80FBD02E003BF303211F406B360
    :10006000C2D0303319F402E07ED0BDD0313319F460
    :1000700003E079D0B8D0383329F402E07ED0B3D091
    :10008000042FB1D0393329F403E077D0ACD0042F5A
    :10009000AAD0303411F493D006BF343671F4A0E600
    :1000A000B0E07DE378D00D937A95E1F7A0E6B0E07B
    :1000B0007DE30D9198D07A95E1F7353681F4A0E68D
    :1000C000B0E07FE168D00D9370D00D937A95D1F7B1
    :1000D000A0E6B0E07EE30D9186D07A95E1F73A3F55
    :1000E00011F439D080D03B3F11F401B77CD03C3FB4
    :1000F00019F48FE37CD177D03D3F19F460D08FE3C2
    :1001000089D03E3F11F45BD001BF3F3F09F401D0DD
    :100110008BCF41B76AE04A5074E141BF1CD0015E09
    :10012000003808F00095061720F410D0033008F4CA
    :100130000DD059D043957A9581F74A50052F01BFCC
    :100140008FE368D050D0042F4ED00895542F0395DC
    :10015000602F0A950895B29BFECF00E00395000042
    :10016000B299FCCF089507B93D9A369A3699FECFD9
    :10017000369A3699FECF05B1089507B9369A369961
    :10018000FECF369A3699FECF44B105B1089503E00B
    :1001900006B9379A089502E207B9369A3699FECF22
    :1001A000369A3699FECF05B1089503E207B9369A1B
    :1001B0003699FECF369A3699FECF05B10895B29B97
    :1001C000FECF1AE31A95F1F700E028E00695B29900
    :1001D000006816E21A95F1F72A95C1F716E21A950A
    :1001E000F1F700950895C19A16E21A95F1F728E003
    :1001F00000FD03C000C0C19A02C0C19800C016E251
    :100200001A95F1F706952A9599F7C19816E21A956D
    :10021000F1F70895E199FECF90E09CBB8EBB0DBB3A
    :10022000E29AE19A08956CC0FFFFFFFFFFFFFFFF16
    :1002F000FFFFFFFFFFFFFFFFFFFFFFFF91CEFFFFAD
    :10030000F89468D0B29901C0F9CFB299FECFB99AEA
    :1003100009E649D034D0302F393C19F40AD001E035
    :1003200042D03A3C09F421D03B3C11F408B3E6CF6B
    :10033000F1CF70E124D0F02F22D0E02FC3E0C7BF6F
    :10034000E8951DD0002E1BD0102EC1E0C7BFE89548
    :10035000E395E395002D27D0012D25D07A9589F7D7
    :10036000E052C5E0C7BFE895089509D0F02F07D047
    :10037000E02F70E2059117D07A95E1F70895B29BCE
    :10038000FECF1AE31A95F1F700E028E00695B2993E
    :10039000006816E21A95F1F72A95C1F716E21A9548
    :1003A000F1F700950895C19A16E21A95F1F728E041
    :1003B00000FD03C000C0C19A02C0C19800C016E28F
    :1003C0001A95F1F706952A9599F7C19816E21A95AC
    :1003D000F1F708958FE30BD041B7401B453018F07B
    :1003E0004C3F08F408958FE302D001BF0895E199CE
    :0A03F000FECF8EBBE09A0DB3089516
    :00000001FF
    ..... es hat also zwischen den Adressen :10023000 und :1002FC00 eine "Lücke", danach fängt der Bootloader an. Wenn man ein eigenes Programm hineinlädt, dann (kann) es so aussehen:
    Code:
    :1000000000C00FE304B90FE305B90AEA05B90FEF21
    :0E0010001FEF05B1009505B91A95F1F7FACF6B
    :00000001FF
    ... bei diesem Progrämmchen "minitest.hex" hatte ich beim Hochladen in den Flash den Speicher gelöscht.

    Beide vorstehenden Abbilder des Flashs und die Fuses sind mit den Programmen LPmikros (Experimentierprogramm und Bootloader) und LPmikros ISP auf die Franzisplatine geladen worden und auf einer Experimentierplatine (quick and dirty) mit einem fliegend angebrachten Programmierstecker unter PonyProg ausgelesen worden.

    Du hast recht, andere fuses kannst Du mit der Entwicklungsumgebung des Lernpaketes nicht setzen oder löschen. Aber Du kannst sehr viele eigene Programme schreiben (z.B. mit AVRStudio) und mit LPmikros ISP in den t13 laden - ohne dass Du den Bootloader benötigst. Irgendwann willst Du aber vielleicht auch einen Quarz benutzen usf. Daher hatte ich mir nachdem ich fast alle Experimente mit dem Lernpaket durchgearbeitet hatte, eine erste Flex2313 (FL ash und EX perimentierplatine) für den tiny2313 selbst gelötet. Die hat den Charme, dass man mit relativ einfach mit ein paar Drahtbrücken auch den t13 flashen und seine fuses ändern kann. Und später hatte ich mehr gelötet *gggg* . . . .
    Ciao sagt der JoeamBerg

  3. #43
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    hallo freunde,

    dank an euch alle, denn ohne euch wäre ich nicht dort, wo ich jetzt bin.
    groß ist die freude!
    mein erstes progrämmchen läuft zufriedenstellend.
    mein spezieller dank gilt besserwessi, denn sein tip mit dem power on reset abfragen hat die problemlösung ohne zusätzliche komponenten oder änderung von fuses möglich gemacht.

    einen kleinen schönheitsfehler hat das programm noch:
    es funktioniert leider nicht astrein mit dem power down sleep modus.
    warum? keine ahnung.
    zum aufwecken braucht es auf int0 einen low level.
    der erste durchlauf funktioniert perfekt (tor auf - zu - auf).
    wenn allerdings das tor nach dem 2. öffnen wieder per impuls (int0) geschlossen werden soll, kommt zum impuls auf pb0 sofort ein hi auf pb4!
    ich kann mir das nicht erklären, da es kein reset int auf pb5 gegeben hat, der tiny also nicht in die POR routine (main) laufen dürfte.

    ich belasse es halt beim "ewigen kreisen" in der loop mit int0 negativ flanke ohne sleep.
    da funktionierts bestens.

    hier mein code, falls es jemanden interessiert:
    Code:
    ;*******************************************************************
    ;* 
    ;* Programm: GTRiegel_PB5
    ;* 
    ;* Version: 1.0
    ;* 
    ;* Erstelldatum: 17.09.2008
    ;* 
    ;* Letztes Änderungsdatum: 04.10.2008
    ;* 
    ;* 
    ;* Portzuordnung:
    ;* PB0	> Impuls Torelektronik
    ;* PB1	< Impuls Tor auf/zu		Int0 Interrupt fallend 
    ;* PB2	< Sensor Riegel offen/zu	ADC
    ;* PB3	> Riegel auf
    ;* PB4	> Riegel zu
    ;* PB5	< Schalter Tor zu		RESET Interrupt 
    ;*
    ;* PB1 und PB5 sind Interrupt gesteuerte Eingänge
    ;* PB2 wird per ADC abgefragt
    ;* 
    ;*******************************************************************
    ; Definitionen
    ;*******************************************************************
    
    #include "tn13def.inc"
    
    .cseg
    .org	0x000		; Interrupt Vektoren	
    	rjmp MAIN	; Hauptprogrammroutine wird aufgerufen bei
    			; POR oder ext. Reset an PB5 (-)
    	rjmp IMPULS	; Interrupt0 an PB1
    	rjmp MAIN	; PinChangeInterrupt wird disabled
    	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übergabe
    .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 
     
    ;*******************************************************************
     MAIN:
    ;-------------------------------------------------------------------
    ; Generelle Initialisierungen
    ;-------------------------------------------------------------------
    ; Stack anlegen
    	ldi	temp,LOW(RAMEND)
    	out	SPL,temp
    
    ; Ports initialisieren
    	ldi	temp,0b00011001	; Register für DDRB in/out laden
    	out	DDRB,temp	; 1,2,5 Eingänge  0,3,4 Ausgänge
    	sbi	PORTB,1		; 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,0b00110010	; 0b001100x0 Sleep-Mode, Int0 Nflanke
    ;	ldi	temp,0b00110000	; 0b00110000 Sleep-Mode, Int0 low level
    	ldi	temp,0b00000010	; 0b00xx0010 INT0 N-Flanke
    	out	MCUCR,temp
    	ldi	temp,0b01000000	; Int0 enable, PinChangeInt disable
    	out	GIMSK,temp	; GIMSK setzen
    
    ; Initialisierung erledigt, Abfrage ob POR oder PB5 Reset Interrupt 
    	cli			; Interrupts disable
    	in	temp,mcusr	; Statusregister einlesen
    	sbrc	temp,1		; Abfrage, wenn POR > skip
    	rjmp	clslatch	; Ext. Reset = Riegel schließen
    	rcall readadc		; Riegelstatus abfragen/setzen
    	rjmp	mloop
    
     CLSLATCH:
    	sbi	PORTB,4		; PB 4 ein = Riegel schließen
    
     WCLS:
    	rcall	readadc
    	sbrs	adcv,1		; skip wenn Riegel geschlossen
    	rjmp	wcls
    	cbi	PORTB,4		; PB 4 aus 
    	ldi	temp,64
    	out	GIFR,temp	; Int0 löschen
    		
     MLOOP:
    ;-------------------------------------------------------------------
    ; Bei SLEEP:
    ; Beendet alle Funktionen, gibt die Interrupts frei und schaltet ab
    ; Interrupts an PB1 (INT0) oder Reset an PB5 aktiviert 
    ; den Processor wieder 
    ;-------------------------------------------------------------------
    	sei			; alle Interrupts frei geben
    ;	sleep			; Power Down, warten auf Interrupts
    	nop
    	rjmp mloop
    	ret
     
    ;*******************************************************************
    ;******************** START INTERRUPT ROUTINEN *********************
    ;*******************************************************************
    
    ;*******************************************************************
     IMPULS:		; OK
    ;-------------------------------------------------------------------
    ; Fragt Status von Tor und Riegel ab und führt entsprechende
    ; Routinen aus
    ;-------------------------------------------------------------------
     	in	savr,SREG 
    	rcall	readadc
    	sbrc	adcv,1		; Bit1=0 = Riegel offen
    	rjmp	opndoor
    	rcall	doorimp		; Tor (+ Riegel) schließen
    	rjmp	endimp	
    
     OPNDOOR:
    	sbi	PORTB,3		; PB 3 ein = Riegel öffnen
    
     WOPN:
    	rcall	readadc
    	sbrc	adcv,1 		; Bit 1=0 wenn offen
    	rjmp	wopn
    	cbi	PORTB,3		; PB 3 aus 
    	rcall	doorimp
    
     ENDIMP:
    	out	SREG,savr
    	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,80		; 80 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 ************************
    ;*******************************************************************
    
    ;*******************************************************************
     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 Bit1 = 0
    ;   5V = Riegel geschlossen		ADCH Bit1 = 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
    
     WRDADC1:			; Schleife bis Messung
    	sbic	ADCSRA,ADSC	; abgeschlossen = ADSC=0
    	rjmp	wrdadc1
    	sbi	ADCSRA,ADSC	; ADC Messung 2tes Mal starten
     
     WRDADC2:
    	sbic	ADCSRA,ADSC	; warten bis ADSC = 0 
    	rjmp	wrdadc2
    	in	adcv,ADCH	; highbyte einlesen
    	cbi	ADCSRA,ADEN	; ADC ausschalten
    	ret
    
    ;*******************************************************************
     DOORIMP:		; OK
    ;-------------------------------------------------------------------
    ; schickt einen Impuls von etwa 1 Sekunde zur Torelektronik
    ;-------------------------------------------------------------------
    	ldi	tsec,1		; Zeit für Impulsspreizung in Sek
    	sbi	PORTB,0		; PB0 ein = Impuls Tor auf
    	rcall	wait		; Impulsspreizung
    	cbi	PORTB,0		; PB0 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, falls gesetzt, vor dem enable wieder gelöscht, damit
    ; dieser nicht nach der generellen Freigabe der Interrupts
    ; ausgeführt wird.
    ;-------------------------------------------------------------------
    	clr	scnt
    	ldi	temp,2
    	out	TIMSK0,temp	; Timer Interrupt freigeben, läuft
    	sei
     WWAIT:
    	cp	scnt,tsec	; Sekunden abgelaufen?
    	brlo	wwait
    	clr	temp
    	out	TIMSK0,temp	; Timer Interrupt sperren, restliche
    				; Interrupts bleiben ein
    	ret
    
    ;************************ ENDE SUBROUTINEN *************************
    .EXIT
    @ oberallgeier:
    bei der normalen verwendung der lernplatine zum programm laden (LPmikros) darf pb5 nicht auf GND gelegt werden !!
    dumme frage: hast du das gemacht? dann gehts nämlich nicht.
    bei mir funktioniert alles wie beschrieben ...
    nur bei LPmikosISP brauchts die brücke.

    lg

  4. #44
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    ... normalen verwendung der lernplatine ... hast du das gemacht? ...
    Nein, bestimmt nicht. Mit dem Bootloader habe ich bei den ersten Versuchen keine Programme hochladen können, eigene Programme schiebe ich deswegen immer mit LPmikroISP rauf, die "normale" ? Funktion der Lernplatine mit dem Experimentierprogramm drauf habe ich zum Testen von allerlei kleinsten Aufbauten.
    Ciao sagt der JoeamBerg

  5. #45
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    hallo joe,

    ich hab mir deine screen shots nun lpmikros genauer angeschaut.
    wie kommst du zur ansicht, wo die ganzen fuses angezeigt werden?
    ich hab das "download" gemacht, aber ich hab nie eine derartige anzeige erhalten.

    übrigens bin ich beim eingehenden testen meines (noch etwas verfeinerten) progrämmchens drauf gekommen, dass - weiß der kuckuck warum - nur in der routine "opndoor" der torimpuls (rcall doorimp) unterschiedlich lange dauert.
    mal 1 sekunde (wie in tsec übergeben) manchmal aber nur ein ganz kurzer flash (vielleicht 0,3 sek).
    woher kann das kommen?
    bei allen anderen aufrufen von "doorimp" ist die zeit konstant ca. 1 sekunde.
    Code:
    ;*******************************************************************
    ;* 
    ;* Programm: GTRiegel_PB5
    ;* 
    ;* Version: 1.2
    ;* 
    ;* Erstelldatum: 17.09.2008
    ;* 
    ;* Letztes Änderungsdatum/-zeit: 06.10.2008 / 20:30
    ;* 
    ;* 
    ;* Portzuordnung:
    ;* PB0	> Impuls Torelektronik
    ;* PB1	< Impuls Tor auf/zu		Int0 Interrupt fallend 
    ;* PB2	< Sensor Riegel offen/zu	ADC Abfrage
    ;* PB3	> Riegel auf
    ;* PB4	> Riegel zu
    ;* PB5	< Schalter Tor zu		RESET Interrupt
    ;*
    ;* PB1 und PB5 sind Interrupt gesteuerte Eingänge (-)
    ;* PB2 wird per ADC abgefragt
    ;* 
    ;*******************************************************************
    ; Definitionen
    ;*******************************************************************
    
    #include "tn13def.inc"
    
    .cseg
    .org	0x000		; Interrupt Vektoren	
    	rjmp MAIN	; bei POR oder ext. Reset an PB5 (-)
    	rjmp IMPULS	; Interrupt0 an PB1
    	reti		; PinChangeInterrupt 		disabled
    	rjmp TMROVF	; TimerOverFlow für WAIT
    	reti		; EEPROM Ready 			disabled
    	reti		; Analog Comparator 		disabled
    	reti		; Timer/Counter Compare Match A	disabled
    	reti		; Timer/Counter Compare Match B	disabled
    	reti		; Watchdog Time-out 		disabled
    	reti		; ADC Conversion Complete 	disabled
    
    .def	SAV1 = R16	; dient zum Sichern des SREG
    .def	SAV2 = R17	; dient zum Sichern des SREG
    .def	TIM1 = R18	; Timer 1 für Wartezeit
    .def	TIM2 = R19	; Timer 2 für Wartezeit
    .def	TSEC = R20	; Sekundenregister für Zeitübergabe
    .def	SCNT = R21	; Sekundenregister für Timer
    .def	ADCV = R22	; enthält Wert von ADCH nach AD-Wandlung 
    .def	TMP1 = R23	; dient für diverse Operationen
    .def	TMP2 = R24	; dient für diverse Operationen
    
    ;*******************************************************************
     MAIN:
    ;-------------------------------------------------------------------
    ; Generelle Initialisierungen
    ;-------------------------------------------------------------------
    ; Stack anlegen
    	ldi	tmp1,LOW(RAMEND)
    	out	SPL,tmp1
    
    ; Ports initialisieren
    	ldi	tmp1,25		; 0b00011001 für DDRB in/out laden
    	out	DDRB,tmp1	; 1,2,5 Eingänge  0,3,4 Ausgänge
    	sbi	PORTB,1		; PB1 PullUp  Ausgänge low
    
    ; ADC initialisieren
    	ldi	tmp1,6		; Reg. für ADC prescaler laden
    	out	ADCSRA,tmp1	; 6 (divider 64) sind ca 18kHz
    	ldi	tmp1,1		; Reg. für ADMUX PB2 laden
    	out	ADMUX,tmp1	; ADMUX setzen
    
    ; Wait-Timer Vorteiler setzen
    	ldi	tmp1,3		; Vorteiler /64
    	out	TCCR0B,tmp1
    
    ; Interrupt Register setzen
    	ldi	tmp1,2		; 0b00000010 PB1 INT0 N-Flanke
    	out	MCUCR,tmp1
    	ldi	tmp1,64		; Bit6: Int0 enable
    	out	GIMSK,tmp1	; GIMSK setzen
    ;-------------------------------------------------------------------
    ; Ende Initialisierungen
    ;-------------------------------------------------------------------
    
    ; Abfrage ob POR oder Ext. Reset Interrupt (PB5) 
    	cli			; disable Interrupts 
    	in	tmp1,mcusr	; Statusregister einlesen
    	sbrc	tmp1,1		; Abfrage, wenn POR > skip
    	rjmp	clslatch	; Ext.Reset (PB5) = Riegel schließen
    	rjmp	mloop
    
     CLSLATCH:
    ;-------------------------------------------------------------------
    ; Dieser Teil schließt den Riegel.
    ; Beendet wird entweder durch ADC "Riegel zu" oder durch Timeout.
    ; Zeitbegrenzung zum Schutz des Zahnriemens falls Riegel festsitzt.
    ;-------------------------------------------------------------------
    	ldi	tmp1,0
    	out	GIMSK,tmp1	; GIMSK Int0 disable
    	ldi	tsec,5		; Wartezeit in Sekunden
    	sbi	PORTB,4		; PB 4 ein = Riegel schließen
    	rcall	strtmr		; Timer starten
     CLOOP:
    	cp	scnt,tsec	; Zeit abgelaufen?
    	brge	eloop
     	rcall	readadc
    	sbrs	adcv,1		; skip wenn Riegel geschlossen
    	rjmp	cloop
     ELOOP:
    	cbi	PORTB,4		; PB 4 aus 
    	rcall	stptmr		; Timer stoppen	
    	ldi	tmp1,64		; Bit6 GIFR + GIMSK
    	in	tmp2,GIFR
    	sbrc	tmp2,6		; Int0 gesetzt? 1=ja > löschen
    	out 	GIFR,tmp1		; Int0 löschen
    	out	GIMSK,tmp1	; Int0 enable
    
     MLOOP:
    ;-------------------------------------------------------------------
    ; Hauptschleife 
    ;-------------------------------------------------------------------
    	sei			; alle Interrupts frei geben
    	nop
    	rjmp mloop
    	ret
     
    ;*******************************************************************
    ;******************** START INTERRUPT ROUTINEN *********************
    ;*******************************************************************
    
    ;*******************************************************************
     IMPULS:		; OK
    ;-------------------------------------------------------------------
    ; Fragt Status von Tor und Riegel ab und führt entsprechende
    ; Routinen aus
    ;-------------------------------------------------------------------
     	in	sav1,SREG 
    	rcall	readadc
    	cpi	adcv,0 		; 0 wenn offen
    	breq	clsdoor		; wenn Tor offen > Torimpuls
    	rcall	opndoor		; sonst Riegel auf, Tor auf
    	rjmp	endimp	
    
     CLSDOOR:
    	rcall	doorimp		; Tor (+ Riegel) schließen
    	rjmp	endimp	
    
     ENDIMP:
    	out	SREG,sav1
    	reti
    
    ;*******************************************************************
     TMROVF:		; OK
    ;-------------------------------------------------------------------
    ; Diese Interruptroutine wird durch den TimerOVF Interrupt
    ; aufgerufen
    ;-------------------------------------------------------------------
    	in	sav2,SREG 
    	clr	tim1 
    	out	TCNT0,tim1	; Timer zurücksetzen
    	inc	tim2
    	cpi	tim2,80		; 80 cylces = ca. Sekunde
    	brlo	tmrovfe
    	clr	tim2
    	inc	scnt		; Sekundenzähler um 1 erhöhen
    
     TMROVFE:
    	out	SREG,sav2
    	reti
    
    ;******************** ENDE INTERRUPTROUTINEN ***********************
    
    ;*******************************************************************
    ;*********************** START SUB ROUTINEN ************************
    ;*******************************************************************
    
    ;*******************************************************************
     OPNDOOR:		; OK	
    ; Mit Zeitbegrenzung zum Schutz des Zahnriemens falls Riegel
    ; festsitzt (angefroren).
    ;-------------------------------------------------------------------
    	ldi	tmp1,0
    	out	GIMSK,tmp1	; Int0 disable
    	ldi	tsec,5		; Wartezeit in Sekunden
    	sbi	PORTB,3		; PB 3 ein = Riegel öffnen
    	clr	tmp2		; Timeout = 0
    	rcall	strtmr		; Timer starten
     STRLP:
    	cp	scnt,tsec	; Zeit abgelaufen?
    	brge	timout
     	rcall	readadc
    	cpi	adcv,0 		; Bit 0=0 wenn offen
    	breq	eopn
    	rjmp	strlp
     TIMOUT:
    	ldi	tmp2,16		; Timeout, Riegel ist blockiert
     EOPN:
    	cbi	PORTB,3		; PB 3 aus 
    	rcall 	stptmr
    	sbrs	tmp2,4		; Riegel blockiert, Tor nicht öffnen
    	rcall	doorimp		; Tor öffnen
    	ldi	tmp1,64		; Bit6 GIFR + GIMSK
    	in	tmp2,GIFR
    	sbrc	tmp2,6		; Int0 gesetzt? 1=ja > löschen
    	out 	GIFR,tmp1		; Int0 löschen
    	out	GIMSK,tmp1	; Int0 enable
    	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 Bit1 = 0
    ; 0,5-2,4V = Riegel Zwischenstellung	ADCH Bit0 = 1
    ;       5V = Riegel geschlossen		ADCH Bit1 = 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
    
     WRDADC1:			; Schleife bis Messung
    	sbic	ADCSRA,ADSC	; abgeschlossen = ADSC=0
    	rjmp	wrdadc1
    	sbi	ADCSRA,ADSC	; ADC Messung 2tes Mal starten
     
     WRDADC2:
    	sbic	ADCSRA,ADSC	; warten bis ADSC = 0 
    	rjmp	wrdadc2
    	in	adcv,ADCH	; highbyte einlesen
    	cbi	ADCSRA,ADEN	; ADC ausschalten
    	ret
    
    ;*******************************************************************
     DOORIMP:		; OK
    ;-------------------------------------------------------------------
    ; schickt einen Impuls von etwa 1 Sekunde zur Torelektronik
    ;-------------------------------------------------------------------
    	ldi	tsec,1		; Zeit für Impulsspreizung in Sek
    	sbi	PORTB,0		; PB0 ein = Impuls Tor auf
    	rcall	wait		; Warteschleife ...
    	cbi	PORTB,0		; PB0 aus
    	ret
    
    ;*******************************************************************
     STRTMR:		; OK
    ;-------------------------------------------------------------------
    ; Start Timer
    ;-------------------------------------------------------------------
    	clr	scnt		; Sekundenzähler leeren
    	ldi	tmp1,2
    	out	TIMSK0,tmp1	; Timer Interrupt freigeben > läuft
    	sei
    	ret
    
    ;*******************************************************************
     STPTMR:		; OK
    ;-------------------------------------------------------------------
    ; Stop Timer
    ;-------------------------------------------------------------------
    	clr	tmp1
    	out	TIMSK0,tmp1	; Timer Interrupt sperren	
    	ret
    
    ;*******************************************************************
     WAIT:			; OK
    ;-------------------------------------------------------------------
    ; Warteschleife für diverse Zeitverzögerungen
    ; Wartezeit wird von aufrufender Routine in TSEC übergeben
    ;-------------------------------------------------------------------
    	rcall	strtmr
     WWAIT:
    	cp	scnt,tsec	; Zeit abgelaufen?
    	brlo	wwait
    	rcall	stptmr
    	ret
    
    ;************************ ENDE SUBROUTINEN *************************
    .EXIT
    sonst läuft das programm einwandfrei - dank euch!

  6. #46
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    Zitat Zitat von HeSt
    ... deine screen shots ... lpmikros genauer angeschaut ... wo die ganzen fuses angezeigt ... hab nie eine derartige anzeige ...
    Ach je, das war missverständlich. Die fuses (zweites Bild) hatte ich mit PonyProg und (m)einem ISP-Kabel ausgelesen; dazu hatte ich den Controller und die erforderliche Verdrahtung in ein Steckbrett montiert. Sorry, dass ich das nicht hingeschrieben hatte. Das erste Bild kennst Du ja von LPmikros - und das deutet eben an, dass Fuses gesetzt werden. Ebenso können mit LPmikro ISP auf der letzten Registerkarte fuses gesetzt werden, um die Taktrate des internen Oszillators in weiten Grenzen zu verstellen. Mit beiden Programmen kann man die Fuses nicht auslesen. Ich fand das immer sehr unpraktisch, weil z.B. beim Setzen der Taktrate im LPmikro ISP nicht klar ist, wie der aktuelle Zustand des Controllers ist. Aber das Ganze hat seinen Sinn als Werkzeug für Anfänger - da wird man dann eben nicht verwirrt von diesen Dingen.

    Zitat Zitat von HeSt
    ... in der routine "opndoor" der torimpuls (rcall doorimp) unterschiedlich lange ...
    Puhhhh - war eine mühevolle Suche (irgendwie lief Dein Code erstmal ne Weile garnicht in meinem Assembler - keine Ahnung warum, aber ich habs hingekriegt).

    Vermutlich unbedeutend, aber es fällt auf: Warum steht "cli;" nach "Ende der Initialisierungen" - das ist "sei" doch noch garnicht aktiv ?

    Fehlerhaft könnte sein, das Du hast in Deiner Hauptschleife "mloop" als ersten Befehl "sei" stehen hast. Nun gilt aber:
    Zitat Zitat von ATtiny13-doc, Rev. 2535I–AVR–05/08, S 13
    When the AVR exits from an interrupt, it will always return to the main program and execute one more instruction before any pending interrupt is served.
    Möglicherweise erzeugt das "nested interrupts" , ohne dass Du es möchtest. Ich hab´s aber nicht ausprobiert. Vielleicht versuchst Du die (nicht sehr hübsche) Methode , dass Du zwei wait-Routinen schreibst - wait1 und wait2 , mit tsec1 und tsec2. Obs hilft, weiss ich aber nicht.
    Ciao sagt der JoeamBerg

  7. #47
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Da werden verschachtelte Interrrupts ausgeführt. Das ist nicht ganz einfach, aber ich kann auch keinen Fehler finden. Immerhin wird das SREG wohl schon mal getrennt für timer und ext. Interrupt gesichert.
    Probleme könnte es geben wenn wärend des wartens ein 2 ter Interrupts an Impuls auftritt, dann geht die sicherung von SREG daneben, denn es wird 2 mal der gleiche Interupt aufgerufen.

  8. #48
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    Zitat Zitat von oberallgeier
    Vermutlich unbedeutend, aber es fällt auf: Warum steht "cli;" nach "Ende der Initialisierungen" - das ist "sei" doch noch garnicht aktiv ?
    das war/ist nur eine vorsichtsmaßnahme.
    sollte aber keinen einfluss auf den ablauf haben.
    Zitat Zitat von oberallgeier
    Fehlerhaft könnte sein, das Du hast in Deiner Hauptschleife "mloop" als ersten Befehl "sei" stehen hast.
    nun, da kann man vor und nachher noch ein NOP einfügen.
    werds probieren und die auswirkung kundtun.
    Zitat Zitat von oberallgeier
    Möglicherweise erzeugt das "nested interrupts" , ohne dass Du es möchtest. Ich hab´s aber nicht ausprobiert. Vielleicht versuchst Du die (nicht sehr hübsche) Methode , dass Du zwei wait-Routinen schreibst - wait1 und wait2 , mit tsec1 und tsec2. Obs hilft, weiss ich aber nicht.
    ist eine möglichkeit. werde es (vielleicht in einer museminute) mal probieren.
    Zitat Zitat von Besserwessi
    Immerhin wird das SREG wohl schon mal getrennt für timer und ext. Interrupt gesichert.
    Probleme könnte es geben wenn wärend des wartens ein 2 ter Interrupts an Impuls auftritt, dann geht die sicherung von SREG daneben, denn es wird 2 mal der gleiche Interupt aufgerufen.
    eben, deshalb habe ich auch 2 getrennte sicherungsregister angelegt.
    und zusätzlich fange ich einen interrupt ab indem ich ihn disabled habe - er also nicht "aktiv" werden kann - und, falls während der wartezeit einer auftritt, indem ich ihn INT0-enable und vor rückkehr abfrage und ggf. lösche.
    das mache ich deshalb, weil ich das problem ja hatte, was sich allerdings in einer doppelten (mit ganz kurzer unterbrechung, kaum zu sehen) aktivzeit von PB3 auswirkte, aber keinen einfluss auf die imulslänge an PB0 hatte.
    aber so lange ich einen impuls bekomme, der ausreicht die torelektronik anzustoßen, soll mir das einstweilen egal sein.
    es ist halt nur nicht nachzuvollziehen warum es so ist.

    danke jedenfalls für eure mühe, sich durch meinen code zu quälen !!

  9. #49
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    update:
    3 NOPs vor und nach dem SEI in MLOOP bringen keine änderung des symptoms.
    anfänglich hat es so ausgesehen, als ob damit das problem der kurzen impulse gelöst wäre, aber nach gut 5 durchläufen das selbe verhalten wieder. egal ob ich dann mal durch abschalten wieder von vorne angefangen hab ...

  10. #50
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.686
    [Hi, HeSt,

    quote="HeSt"]update:
    3 NOPs vor und nach dem SEI in MLOOP bringen keine änderung des symptoms.
    anfänglich hat es so ausgesehen, als ob damit das problem der kurzen impulse gelöst wäre, aber nach gut 5 durchläufen das selbe verhalten wieder. egal ob ich dann mal durch abschalten wieder von vorne angefangen hab ...[/quote]
    -------------------------------------------------------

    Schade dass Di nop´s nicht helfen .

    Du verwendest den Sekundentimer SCNT offenbar für mehrere Routinen, kann da ein/der Fehler liegen? Der Wert wird doch möglicherweise von der einen Routinen gerade benutzt, und dann kommt die Interruptgeschicht - die das Wait auch benutzt. Wäre dumm.

    Ausserdem wird SCNT im WAIT mit TSEC verglichen, und TSEC kann sowohl den Wert 5 haben - in CLSLATCH und OPNDOOR - als auch den Wert 1 - in DOORIMP. Da werden sich über kurz oder lang die Interrupts sicher in die Quere kommen. Mögliche Abhilfe:
    In der ISR vor dem rcall wait ein push tsec machen und vor dem reti ein pop tsec ? ?

    Aber bestimmt unschön ist es in STRTMR den Interrupt generell zu erlauben - "sei". Dann bekommst Du (wie schon erwähnt) nested interrupts - eine hübsche Geschichte die mit äusserster Vorsicht programmiert werden sollte/kann/muss. Sonst geht das schief
    Ciao sagt der JoeamBerg

Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte

Berechtigungen

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

Labornetzteil AliExpress