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