;************************************************************************************ ;Software License Agreement ; ;The software supplied herewith by Erlich Industrial Development, Corp. EID, Corp. ;(the "Company") is intended and supplied to you, the Company’s customer, for use ;solely and exclusively on EID micro-base Kits and interface board products line. ;The software is owned by the Company and/or its supplier, and is protected under ;applicable copyright laws. All rights are reserved. Any use in violation of the ;foregoing restrictions may subject the user to criminal sanctions under applicable ;laws, as well as to civil liability for the breach of the terms and conditions of ;this license. ; ;THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, WHETHER EXPRESS, ;IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF ;MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. ;THE COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR ;CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. ;************************************************************************************ ;Filename: leveler_L4.asm ;Author: Dr. Ron Erlich & Keith Youngblood ;Date: 2008-06-16 ;Version: 3.0.0 ;Tabs: 8 (for proper code indenting, set your editor tab size to 8) ;Description: This program displays (via 4 LEDs) the voltage of a battery (or other ; input on a number of LED's. It includes hysteresis to minimize jitter ; at boundaries between levels. ;************************************************************************************ ; Revision History ; 2008-09-08 - v3.0.0 -- Initial release ;************************************************************************************ list p=12F675 ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ; ==================================================================================== ; ==================================================================================== ; Defines ; ==================================================================================== ; ==================================================================================== #define VERSION '1.0.4' #define BANK1 banksel 0x80 ; Select Bank1 #define BANK0 banksel 0x00 ; Select Bank0 ; ============================================================================ ; ========================= Threshold definitions ============================ ; ============================================================================ ; To calculate the values need for these threshold definitions, you will need ; to know the voltage ranges you wish to have the LED's display. You must ; also determine what hysteresis amount you wish to have between the ranges ; so as to minimize and/or eliminate jitter caused by noise and other factors. ; You may also need to take into account any scaling of the voltage done by ; resistor dividers and/or amplification stages. ; ; To calculate the values from voltages (0-5v range) determined to be ; appropriate for your application, use the following equation: ; ; THRESH_VALUE = V / 0.0196 ; ; e.g. For a 3.5 volt threshold level, take 3.5 and divide it by 0.0196. ; This will produce the value 178.57 (round it down to 178) ; Using 178 as a threshold value will cause the LED to transition ; at 3.5 volts. ; ; To reverse the calculation, take a threshold value and multiply it by ; 0.0195 to find the voltage. ; ; The following defines specify the level thresholds desired ; The range is from 0 to 255 (the range of the 8-bit ADC) ; The high values must be greater than or equal to the low values ; These values can also be computed using assembler directives should you ; wish to specify them using other values ; i.e. A threshold centered between the H and L points ; #define THR_1 d'128' ; #define HYST d'4' ; #define THRESH_1_H (THR_1 + (HYST / 2)) ; would equal 0x81 ; #define THRESH_1_L (THR_1 - (HYST / 2)) ; would equal 0x7D #define THRESH_1_H d'178' ; 3.5 volts (3.49v) #define THRESH_1_L d'173' ; 3.4 volts (3.39v) ; Example of very small hysteresis ; This threshold will experience jitter #define THRESH_2_H d'127' ; 2.49 volts #define THRESH_2_L d'126' ; 2.48 volts ; a larger hysteresis overlap #define THRESH_3_H d'76' ; 1.5 volts #define THRESH_3_L d'66' ; 1.3 volts ; ============================================================================ ; ============================================================================ ; ============================================================================ #define STATE_MASK B'00000011' ; The following define the bit patterns to send to GPIO ; upon entering the respective state #define LED_1_ON b'00111011' ; Bit pattern for State 1 #define LED_2_ON b'00111110' ; Bit pattern for State 2 #define LED_3_ON b'00111101' ; Bit pattern for State 3 #define LED_4_ON b'00011111' ; Bit pattern for State 4 #define LED_TRIS b'11011000' ; Tris pattern for port I/O #define ANSelect b'00011000' ; Used to configure AD ; x------- ; Not implemented ; -001---- ; ADCS<2:0> -- FOSC/8 ; ----1000 ; ANS3:ANS0 -- AN3 = analog #define ADControl b'00001101' ; Used to configure AD ; 0------- ; ADFM -- Left justified ; -0------ ; VCFG -- Vref = VDD ; --xx---- ; Not implemented ; ----11-- ; CHS1:CHS0 -- ADC Ch3 select ; ------0- ; GO /DONE -- Not in progress ; -------1 ; ADON -- Turn on ADC ; ==================================================================================== ; ==================================================================================== ; RAM allocation declaration ; ==================================================================================== ; ==================================================================================== cblock 0x20 ; These variables are for context saving during an interrupt WTEMP :1 ; register used in Interrupt Routine STATUS_TEMP :1 ; register used in Interrupt Routine PCLATH_TEMP :1 ; register used in Interrupt Routine FSR_TEMP :1 ; register used in Interrupt Routine ; A byte for any needed program flags FLAGS :1 ; register used to set flags ; Program variables WHICH_STATE :1 ; Holds curreent level state ADC_VALUE :1 ; Holds last ADC conversion value endc ; ==================================================================================== ; ==================================================================================== ; Program start ; ==================================================================================== ; ==================================================================================== org 0x0000 nop ; Inserted for ICD2 goto Init ; Skip interrupt handler ; ==================================================================================== ; ==================================================================================== ; Interrupt handler ; ==================================================================================== ; ==================================================================================== org 0x0004 Isr movwf WTEMP ; Save off current W register contents movf STATUS,w clrf STATUS ; Force to page0 movwf STATUS_TEMP movf PCLATH,w movwf PCLATH_TEMP ; Save PCLATH movf FSR,w movwf FSR_TEMP ; Save FSR BANK1 ; BANK1 ;************************************************************************************* ; Interrupt Source Checks ;************************************************************************************* ADIFInterruptCheck movf PIE1,w andlw 0x40 btfsc STATUS,Z ; Are the ADC interrupts enabled? goto EndIsr ; No BANK0 movf PIR1,w ; Check if conversion completed BANK1 andlw 0x40 btfsc STATUS,Z ; Conversion done? goto EndIsr ; No ; ADC is done converting, read 8 bit value and store in ADC_VALUE ; then clear the interrupt flag and start another conversion A_DConverterInterrupt BANK0 ; BANK0 movf ADRESH,W ; Move the most significant byte of ; A/D Result to W movwf ADC_VALUE ; The A/D result is moved to ADC_VALUE ; and will be compared bcf PIR1,ADIF ; Clear ADC Interrupt Flag bsf ADCON0,GO ; Start A/D ; All done, restore system variables and return from interrupt EndIsr clrf STATUS ; Select Bank0 movf FSR_TEMP,w movwf FSR ; Restore FSR movf PCLATH_TEMP,w movwf PCLATH ; Restore PCLATH movf STATUS_TEMP,w movwf STATUS ; Restore STATUS swapf WTEMP,f swapf WTEMP,w ; Restore W without corrupting STATUS bits retfie ; Return from interrupt ; ==================================================================================== ; ==================================================================================== ; Program initialization ; ==================================================================================== ; ==================================================================================== Init call 0x3FF ; retrieve factory calibration value ; comment instruction if using simulator, ; ICD2, or ICE2000 BANK1 movwf OSCCAL ; update register with factory cal value movlw LED_TRIS movwf TRISIO ; Tri-State set to LED_TRIS value BANK0 ; BANK 0 clrf GPIO ; Clear Port BANK1 ; BANK 1 clrf VRCON ; Vref Off (????) BANK0 ; BANK 0 movlw 0x07 movwf CMCON ; Comparator Off BANK1 ; BANK 1 bsf PIE1,ADIE ; Set the ADC interrupt flag BANK0 bsf INTCON,PEIE ; Interrupt on ADC Enabled (????) bcf PIR1,ADIF ; Clear ADC Interrupt Flag bsf INTCON,GIE ; Turn on Global Interrupts BANK1 movlw ANSelect movwf ANSEL ; Configure AN0 & prescale to A/D BANK0 ; BANK 0 movlw ADControl movwf ADCON0 ; Select AN0, Left justified & enables A/D nop nop nop nop ; Give 4 uS delay before starting A/D bsf ADCON0,GO ; Start A/D movlw 0x03 movwf WHICH_STATE ; Set State to lowest clrf ADC_VALUE ; Set ADC_VALUE to zero (lowest) ; ==================================================================================== ; ==================================================================================== ; Main program loop ; ==================================================================================== ; ==================================================================================== Main movf WHICH_STATE, w andlw STATE_MASK addwf PCL, f goto Test_1 goto Test_2 goto Test_3 goto Test_4 Test_1 ifTest_1_L movlw THRESH_1_L ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w ; btfsc STATUS, C ; Is ADC_VALUE less than low threshold? goto endifTest_1_L ; No incf WHICH_STATE,f ; Yes, the threshold has been exceeded, ; change to new state endifTest_1_L goto Display ; Done, display it Test_2 ifTest_2_H movlw THRESH_1_H ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w btfss STATUS, C ; Is ADC_VALUE greater than high threshold? goto endifTest_2_H ; No decf WHICH_STATE,f ; Yes, the threshold has been exceeded, ; change to new state endifTest_2_H ifTest_2_L movlw THRESH_2_L ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w btfsc STATUS, C ; Is ADC_VALUE less than low threshold? goto endifTest_2_L ; No incf WHICH_STATE,f ; Yes, the threshold has been exceeded, ; change to new state endifTest_2_L goto Display ; Done, display it Test_3 ifTest_3_H movlw THRESH_2_H ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w btfss STATUS, C ; Is ADC_VALUE greater than high threshold? goto endifTest_3_H ; No decf WHICH_STATE,f ; The threshold has been exceeded, ; change to new state endifTest_3_H ifTest_3_L movlw THRESH_3_L ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w btfsc STATUS, C ; Is ADC_VALUE less than low threshold? goto endifTest_3_L ; No incf WHICH_STATE,f ; The threshold has been exceeded, ; change to new state endifTest_3_L goto Display ; Done, display it Test_4 ifTest_4_H movlw THRESH_3_H ; Compare the low threshold to last ADC_VALUE subwf ADC_VALUE,w btfss STATUS, C ; Is ADC_VALUE greater than high threshold? goto endifTest_4_H ; No decf WHICH_STATE,f ; The threshold has been exceeded, ; change to new state endifTest_4_H ; ==================================================================================== ; ==================================================================================== ; Display state on LED's ; ==================================================================================== ; ==================================================================================== Display movf WHICH_STATE, w ; Mask out the high order bits of andlw STATE_MASK ; WHICH_STATE addwf PCL, f ; The program clock (PCL) is incre- goto State0 ; mented by WHICH_STATE in order goto State1 ; to go to the appropiate routine goto State2 goto State3 State0 ; Turns on LED 1 bcf STATUS, RP0 ; Bank 0 movlw LED_1_ON ; move predefined value to GPIO movwf GPIO goto Main ; go back to Main State1 ; Turns on LED 2 bcf STATUS, RP0 ; Bank 0 movlw LED_2_ON ; move predefined value to GPIO movwf GPIO goto Main ; go back to Main State2 ; Turns on LED 3 bcf STATUS, RP0 ; Bank 0 movlw LED_3_ON ; move predefined value to GPIO movwf GPIO goto Main ; go back to Main State3 ; Turns on LED 4 bcf STATUS, RP0 ; Bank 0 movlw LED_4_ON ; move predefined value to GPIO movwf GPIO goto Main ; go back to Main org 0x330 ; Write data to memory address 330 HEX dt "ELECTRONIC LEVELER PIC 12F675 BY DR R. ERLICH c/o EID CORP. AND " dt "BY KEITH YOUNGBLOOD c/o YB TECH. AUG. 2008 " dt "THIS SOFTWARE IS PROVIDED ON AN AS IS CONDITION. " ; "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" ; ==================================================================================== ; ==================================================================================== ; End of program ; ==================================================================================== ; ==================================================================================== end ; Required directive