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!
						
Lesezeichen