?? lampe.asm
字號:
; ******************************************************************************
; * Programm zur Steuerung der Halogenlampe
; * erstellt im August 2002 von Hannes Studeny
; *
; * Taktrate: 4 MHz --> 1 Mio Befehle pro Sekunde --> 1 Befehl ben鰐igt 1 Microsekunde
; ******************************************************************************
; *
; * Funktionalit鋞:
; * ===============
; * an RA0 wird die Spannung des Akkus gemessen
; * an RC2 wird ein PWM Signal, in Abh鋘gigkeit der gemessenen Spannung, erzeugt.
; * an RB2 wird der Taster angeschlossen
; * mit dem Taster wird die Lampe durch einen langen Tastendruck (mehr als 5 Sekunden) ein- bzw. ausgeschaltet
; * wenn die Lampe eingeschaltet ist, kann durch kurze Tastendr點ke (1 bis 2,5 Sekunden) zwischen folgenden
; * Modi gewechselt werden:
; * 100%
; * 80%
; * 50%
; * SOS
; *
; * am A/D Wandler k鰊nen Spannungen von 15V bis 10V gemessen werden
; * werden weniger als 11,3 Volt gemessen, wird die Lampe automatisch abgeschaltet (PWM wird auf 0% eingestellt).
; * werden mehr als 12 Volt gemessen, regelt der PWM Ausgang die Spannung auf 12 Volt herunter
; *
; *
; * Programmablauf:
; * ===============
; * zuerst wird das PWM-Modul und der AD-Wandler initialisiert
; * in einer Endlosschleife erfolgt folgende Verarbeitung:
; * 1. die Akku-Spannung wird gemessen
; * 2. der PWM Output wird angepasst
; * 3. der Taster wird abgefragt und entsprechend verarbeitet
; *
; * die Ausgangsspannung vom OpAmp errechnet sich folgendermassen:
; * Ua = 2/3*Ue - 5
; * 15V entsprechen 5V und 10V entsprechen 1,67V
; *
; * Ua = 5/256*ADRESH
; * Ue = (Ua+5)*3/2
; * PWM = 12 / Ue
; * CCPR1L = 249*PWM
; *
list p=16f870
include "p16f870.inc"
; __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_ON & _LVP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC
; #define DEBUG
; ****************
; *** Definitionen
; ****************
BIT_ARRAY equ 0x20
CCPR1L_TMP equ 0x21
SOS_COUNTER equ 0x22
BIT_ARRAY2 equ 0x23
BLINK_COUNTER equ 0x24
LOWBAT_COUNTER equ 0x25
W_TEMP equ 0x28
STATUS_TEMP equ 0x2A
PCLATH_TEMP equ 0x2B
FSR_TEMP equ 0x2C
COUNTER_TMR0 equ 0x2D
d1 equ 0x2E
d2 equ 0x2F
d3 equ 0x30
PIN_TASTER equ 0
PWM_OUT equ 2
ON_OFF equ 3
LOWBAT equ 4
BLINKEN equ 5
LED_GREEN equ 1
LED_RED equ 2
BIT_LED100 equ 0
BIT_LED80 equ 1
BIT_LED50 equ 2
BIT_LEDSOS equ 3
BIT_ONOFF equ 4
BIT_TASTER equ 5
BIT_TASTER_LONG equ 6
BIT_BLINKEN equ 0
BIT_LOWBAT equ 1
PROZENT_100 equ D'249'
PROZENT_80 equ D'199'
PROZENT_50 equ D'125'
COUNTER_VALUE_BLINK equ D'40'
COUNTER_VALUE_LOWBAT equ D'30'
; Ziele
w equ 0 ; W-Register ist Zielregister
f equ 1 ; f-Register ist Zielregister
; *********************
; *** Macrodefinitionen
; *********************
BANK_0 macro ; Select Bank 0
bcf STATUS,RP0
bcf STATUS,RP1
errorlevel +302
endm
BANK_1 macro ; Select Bank 1
bsf STATUS,RP0
bcf STATUS,RP1
endm
BANK_2 macro ; Select Bank 2
bcf STATUS,RP0
bsf STATUS,RP1
endm
BANK_3 macro ; Select Bank 3
bsf STATUS,RP0
bsf STATUS,RP1
endm
; *******************************************************
; *** hier beginnt das eigentliche Programm
; *******************************************************
org 0x00
goto main
org 0x04
; hier steht die Interruptroutine
; PROLOG
movwf W_TEMP
swapf STATUS,w
clrf STATUS
movwf STATUS_TEMP
movf PCLATH,w
movwf PCLATH_TEMP
clrf PCLATH
bcf STATUS,IRP
movf FSR,w
movwf FSR_TEMP
BANK_0
btfsc INTCON,T0IF
call TIMER0_INTERRUPT
btfsc INTCON,INTF
call PORT_CHANGE_INTERRUPT
btfsc PIR1,TMR1IF
call TEST_OP_AMP
INTERRUPT_EPILOG
movf PCLATH_TEMP,w
movwf PCLATH
swapf STATUS_TEMP,w
movwf STATUS
swapf W_TEMP,f
swapf W_TEMP,w
retfie
main
; jetzt gehts erst so richtig los...
BANK_1
errorlevel -302
bcf TRISC,PWM_OUT ; 0...Output
bcf TRISC,ON_OFF
bsf TRISC,LOWBAT ; 1...Input
bsf TRISC,BLINKEN
BANK_0
call LAMP_OFF
clrf PORTB ; PORTB initialisieren
clrf BIT_ARRAY
clrf BIT_ARRAY2
movlw COUNTER_VALUE_BLINK
movwf BLINK_COUNTER
movlw COUNTER_VALUE_LOWBAT
movwf LOWBAT_COUNTER
call InitPwm
BANK_1
errorlevel -302
clrf TRISB ; alle Pins von PORTB ausser RB0 als Output definieren
bsf TRISB,PIN_TASTER ; 1...Input
bcf OPTION_REG,T0CS ; internal Cycle clock for Timer0
bcf OPTION_REG,NOT_RBPU ; activate Pullups on RBx
bcf OPTION_REG,PSA ; assign prescaler to Timer0
bcf OPTION_REG,INTEDG ; Interrupt on falling edge of RB0
ifdef DEBUG
bsf OPTION_REG,PSA ; assign prescaler to WDT
bcf OPTION_REG,PS2 ; prescaler rate 1:1
bcf OPTION_REG,PS1
bcf OPTION_REG,PS0
else
bsf OPTION_REG,PS2 ; prescaler rate 1:256
bsf OPTION_REG,PS1
bsf OPTION_REG,PS0
endif
BANK_0
; ************ TIMER1 Initialisieren
bsf T1CON,TMR1ON ; Timer1 einschalten
BANK_1
bsf PIE1,TMR1IE ; Timer1 Interrupt enablen
BANK_0
clrf INTCON ; zuerst alle Interrupts deaktivieren und l鰏chen
bsf INTCON,INTE ; Interrupt an RB0 aktivieren
bsf INTCON,PEIE ; f黵 Timer1 Interrupt notwendig
bsf INTCON,GIE ; globales Interrupt enable Bit
movlw D'0'
movwf CCPR1L
bsf PORTB,LED_GREEN ; test
call Delay1
bcf PORTB,LED_GREEN ; test
bsf PORTB,LED_RED ; test
call Delay1
bcf PORTB,LED_RED ; test
LOOP
; call TEST_OP_AMP wir als Interrupt gel鰏t
btfsc BIT_ARRAY2,BIT_BLINKEN
call LAMP_BLINKEN
btfsc BIT_ARRAY2,BIT_LOWBAT
call LAMP_LOWBAT
btfss BIT_ARRAY,BIT_ONOFF
goto LOOP
btfsc BIT_ARRAY,BIT_LEDSOS
call SOS_MODE
btfss BIT_ARRAY,BIT_ONOFF
call LAMP_OFF
bcf BIT_ARRAY,BIT_TASTER
goto LOOP
LAMP_LOWBAT
bcf INTCON,GIE ; keine Interrupts (Schalter) mehr zulassen
bsf PORTB,LED_RED
call RESET
bsf PORTB,LED_GREEN ; test
ENDE
bcf PORTB,LED_GREEN
bcf INTCON,GIE
call LAMP_OFF
goto ENDE
; *********************************************************************************
; * nur wenn der Schwellenwert 5 mal hintereinander unterschritten wird, gilt er...
; *********************************************************************************
TEST_OP_AMP
bcf PIR1,TMR1IF ; Interruptflag Timer0 wieder l鰏chen
btfsc PORTC,BLINKEN
goto TEST_OP_BLINKEN
movlw COUNTER_VALUE_BLINK
movwf BLINK_COUNTER
TEST_OP_AMP_1
btfsc PORTC,LOWBAT
goto TEST_OP_LOWBAT
movlw COUNTER_VALUE_LOWBAT
movwf LOWBAT_COUNTER
TEST_OP_AMP_2
btfsc BIT_ARRAY,BIT_LEDSOS ; bei SOS gibt es kein Blinken wegen Low-Bat
bcf BIT_ARRAY2,BIT_BLINKEN
return
TEST_OP_BLINKEN
decfsz BLINK_COUNTER,f
goto TEST_OP_AMP_1
bsf BIT_ARRAY2,BIT_BLINKEN
goto TEST_OP_AMP_1
TEST_OP_LOWBAT
decfsz LOWBAT_COUNTER,f
goto TEST_OP_AMP_2
bsf BIT_ARRAY2,BIT_LOWBAT
goto TEST_OP_AMP_2
; **************************************************************************************
LAMP_BLINKEN
bsf PORTB,LED_GREEN
btfss BIT_ARRAY,BIT_ONOFF ; Lampe ist ausgeschaltet
return
call LAMP_OFF
call Delay10
call LAMP_ON
call Delay1
call TEST_OP_AMP
call Delay1
call TEST_OP_AMP
call Delay1
call TEST_OP_AMP
return
;************************************************
;* Lampe ausschalten
;************************************************
LAMP_OFF
bsf PORTC,ON_OFF ; Lampe ausschalten
return
;************************************************
;* Lampe einschalten
;* PWM wird eingeschaltet und mit dem Wert vom CCPR1L_TMP initialisiert
;************************************************
LAMP_ON
movlw D'0'
movwf CCPR1L ; CCPR1L = 0%
call Delay1000 ; ein bisschen warten, damit sich die PWM einstellen kann
bcf PORTC,ON_OFF ; Lampe mit Softstart einschalten
call SOFTSTART ; Lampe sanft hochfahren
return
;************************************************
;* in einer Schleife wird das Tastverh鋖tnis von 0% bis auf
;* den in CCPR1L_TMP vorhandenen Wert gesteigert
;* daf黵 werden ca. 250 ms ben鰐igt.
;************************************************
SOFTSTART
movlw D'0'
movwf CCPR1L ; CCPR1L = 0%
SOFTSTART_LOOP
incf CCPR1L,f
incf CCPR1L,f
ifdef DEBUG
movlw D'250'
movwf CCPR1L
else
call Delay1000
endif
movf CCPR1L,w
subwf CCPR1L_TMP,w ; w = CCPR1L_TMP - w
btfsc STATUS,C
goto SOFTSTART_LOOP
movf CCPR1L_TMP,w
movwf CCPR1L ; urspr黱glichen Wert von CCPR1L wieder herstellen
return
SOS_MODE
movlw 3
movwf SOS_COUNTER
SOS_MODE_1
call PAUSE_SHORT
btfsc BIT_ARRAY,BIT_TASTER
goto SOS_MODE_ENDE ; Taster wurde gedr點kt
call PAUSE_LONG ; lang
btfsc BIT_ARRAY,BIT_TASTER
goto SOS_MODE_ENDE ; Taster wurde gedr點kt
decfsz SOS_COUNTER,f
goto SOS_MODE_1
movlw 3
movwf SOS_COUNTER
SOS_MODE_2
call PAUSE_SHORT
btfsc BIT_ARRAY,BIT_TASTER
goto SOS_MODE_ENDE ; Taster wurde gedr點kt
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -