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