; 29JUL13 ; DEVICE = 16F628A ; Electroluminescent Lamp Controller ; Outputs 10 kHz PWM drive for MOSFET switch, comparator feedback for voltage, 1.0 kHz drive for EL lamp ; Filename: elbl.asm LIST P=16F628a, F=INHX8M #include <p16f628a.inc> __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_ON & _LVP_OFF & _CP_OFF ; Equates RESET_V EQU 0x00 ; Address of RESET Vector OSC_FREQ EQU D'4000000' ; Oscillator Frequency is 4.0 MHz ; Registers #define EL1 PORTB,1 ; EL lamp one electrode #define EL2 PORTB,2 ; EL lamp other electrode #define FET PORTB,3 ; Booster FET gate (CCP1) #define PKD PORTB,4 ; Set if output voltage has peaked #define COMPLO PORTA,0 ; Lower voltage input for EL lamp voltage #define COMPHI PORTA,1 ; Upper voltage input for EL lamp voltage ORG 0x00 GOTO START ORG 0x04 ; Interrupt handlers ; NOTE: Since virtually every part of this program runs inside an interrupt handler, it's not necesssary ; to back up any critical registers when entering or exiting the handler. BTFSC PIR1,TMR1IF ; Check to see if the interrupt was caused by a TIMER1 rollover Overflow) GOTO Drive ; 0.5 ms timer for EL driver BCF PIR1,TMR2IF ; In case Timer2 generates an interrupt RETFIE ; Leave the interrupt handler Drive ; EL driver, also comparator for output voltage BCF PIR1,TMR1IF ; Clear Interrupt Source MOVLW 0xFE ; Preload TIMER1 (0.5 ms) MOVWF TMR1H CLRF TMR1L CALL ToglEL ; Toggle EL outputs BTFSC PKD ; If set HV is falling, check COMPLO GOTO Falling BTFSC CMCON,C2OUT ; Test for upper voltage high RETFIE BSF PKD ; HV peaked, reduce PWM drive to FET MOVLW 0x09 ; Set PWM to 10% duty cycle MOVWF CCPR1L RETFIE Falling BTFSS CMCON,C1OUT ; Test for lower voltage high RETFIE BCF PKD ; Lower voltage reached, set PWM to 85% duty cycle MOVLW 0x55 MOVWF CCPR1L RETFIE START CLRF STATUS ; Do initialization, Select bank 0 CLRF INTCON ; Clear int-flags, Disable interrupts CLRF PCLATH ; Keep in lower 2KByte MOVLW B'00000010' ; AN0 & AN1 Inputs Multiplexed to Comparators, Outputs Inverted MOVWF CMCON BSF STATUS, RP0 ; Select bank 1 MOVLW 0xFF MOVWF TRISA ; RA7-0 Inputs CLRF TRISB ; RB7-0 Outputs CLRF OPTION_REG ; Clear everything in OPTION reg (see par. 4.2.2.2) MOVLW B'11101100' ; Set voltage reference to 0.50*VDD, output on RA2 (input) MOVWF VRCON BCF STATUS, RP0 ; Select bank 0 CLRF PORTB ; Make all PORT B outputs Low ; Enable interrupts BCF INTCON,INTF ; Clear INTF flag before enabling interrupts BCF INTCON,T0IF ; Clear T0IF (TIMER0 Interrupt Flag) before enabling interrupts BCF PIR1,TMR1IF ; Clear TMR1IF (TIMER1 Interrupt Flag) before enabling interrupts BCF PIR1,TMR2IF ; Clear TMR2IF (TIMER1 Interrupt Flag) before enabling interrupts BCF INTCON,INTE ; Clear interrupt on RB0/INT pin (an External interrupt) BSF INTCON,PEIE ; Enable PEIE (PEripheral Interrupt Enable - for TIMER1 and 2) BSF STATUS,RP0 ; Go to bank 1 BSF PIE1,TMR1IE ; Enable interrupt on TIMER1 overflow (when the TMR1 register pair wraps around from 0xFFFF to 0x0000) BSF PIE1,TMR2IE ; Enable interrupt on TIMER2 overflow BCF PIE1,CMIE ; Disable interrupt on comparator output change BCF STATUS,RP0 ; Go to bank 0 BSF INTCON,GIE ; Enable global interrupts ; Setup Timer1 BCF T1CON,T1CKPS1 ; These set the TIMER1 prescaler. Values: BCF T1CON,T1CKPS0 ; 00=1:1 01=1:2 10=1:4 11=1:8 BCF T1CON,T1OSCEN ; Turn off the TIMER1 oscillator to save power (we don't need it because we're using the internal oscillator) BCF T1CON,TMR1CS ; Select the internal oscillator for TIMER1 BSF T1CON,TMR1ON ; Enable TIMER1 MOVLW 0xFE ; Preload TIMER1 (0.5ms) MOVWF TMR1H CLRF TMR1L ; Setup PWM MOVLW B'00001100' ; Set CCP module to PWM MOVWF CCP1CON MOVLW 0x55 ; Set PWM to 85% duty cycle MOVWF CCPR1L MOVLW 0x04 ; Set T2CON for TMR2 1:1 pre/postcale and enabled MOVWF T2CON BSF STATUS, RP0 ; Select bank 1 MOVLW 0x63 ; Set PWM period to 100 us MOVWF PR2 BCF STATUS, RP0 ; Select bank 0 MAIN GOTO MAIN ; Loop forever ; Subroutine ToglEL ; Toggles EL outputs CLRWDT ; Clear Watchdog (runs every 0.5 ms) BTFSC EL1 ; Test for "10" GOTO SET01 BSF EL1 ; SET "10" BCF EL2 RETURN SET01 BCF EL1 BSF EL2 RETURN END