LIST P=12F675,R=HEX ; ; Monitor for Li-Ion / Li-Poly Battery Packs with cell balance connector ; SUN, PU-NENG ; ; VERSION 2.0 (DEC/12/2005) ; Add unbalance detector nominal 0.2V, actually 0.1~0.15V ; ; VERSION 1.0 (DEC/08/2005) ; 3cell, Cut off at 3.0 V, ;============================================= ; Voltage AN0 = cell 0 ; Voltage AN1 = cell (0+1)/2 ; Voltage AN2 = cell (0+1+2)/3 ; ; Voltage cell 0 = AN0 ; Voltage cell 1 = (AN1*2)-AN0 ; Voltage cell 2 = (AN2*3)-(AN1*2) ;============================================== ; ;---- SYSTEM CONFIG ---- __CONFIG H'3FA4' ;_INTRC_OSC_NOCLKOUT,_MCLRE_OFF,WDT OFF,PWRTE ON ; ;----- SYSTEM --------- W EQU 0 ;d VALUE FOR INCF...... F EQU 1 ;d VALUE TMR0 EQU 1 ;TIMER 0 PCL EQU 2 ;PROGRAM COUNTER STATUS EQU 3 FSR EQU 4 ;BUFFER OF INDIRECT ADDR GPIO EQU 5 OPTION_reg EQU 0x81 TRISIO EQU 0x85 OSCCAL EQU 0x90 RP0 EQU 5 CMCON EQU 0x19 ;CMCON REGISTER ANSEL EQU 0x9F ;ANALOG SEL ADCON0 EQU H'1F' ADRESH EQU H'1E' GO EQU 1 C EQU 0 ;status Z EQU 2 ;status ;===================================== ; ;---- USER registers DEFINE ------ ; TEMP0 EQU H'20' TEMP1 EQU H'21' ; TEMP2 EQU H'22' ; TEMP3 EQU H'23' ; SOUND_TEMP1 EQU H'24' ; SOUND_TEMP2 EQU H'25' ; SOUND_TEMP3 EQU H'26' ; FLAG_REG EQU H'27' ; ACCaLO equ 2A ACCaHI equ 2B ACCbLO equ 2C ACCbHI equ 2D ACCcLO equ 2E ACCcHI equ 2F ; CELL0_V equ 31 CELL1_V equ 32 CELL2_V equ 33 ; ;============================================ ;---- VARIABLES DEFINE ---- ; LOW_VOLTAGE EQU D'153' ; (3.0V/5.0V)*255= 153 ;LOW_VOLTAGE EQU D'158' ; (3.1V/5.0V)*255= 158 ;LOW_VOLTAGE EQU D'163' ; (3.2V/5.0V)*255= 163 ; UNBAL_VOLTAGE EQU D'10' ; (0.2V/5.0V)*255= 10 ; ;nominal 0.2V, actually 0.1~0.15V ;---- HARDWARE DEFINE ---- ; AN0 EQU 0 AN1 EQU 1 AN2 EQU 2 SOUND_PIN EQU 4 ;INVERSE LED_PIN EQU 5 ;INVERSE ; ;============================================ ;============== MAIN PROGRAM ============ ; ;--- RESTORE OSC CALIBRATION --------- ORG 0 BSF STATUS,RP0 ;;BANK1 CALL 3FFh MOVWF OSCCAL ;RESTORE OSC CALI ;---------------------------------- START CALL INIT_SYS call self_test MAIN call output_audio ;CALL GET_Votlage GOTO MAIN ;===================================== INIT_SYS bsf status,RP0 ;bank1 MOVLW H'C0' ;T0CS=0, TO ENABLE GP2 MOVWF OPTION_reg MOVLW B'00000111' ;GPIO 0~2 =input MOVWF TRISIO MOVLW B'00100111' MOVWF ANSEL ;T32, GPIO 0~2 ARE ANALOG BCF STATUS,RP0 ; BANK0 MOVLW B'00000001' MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON BSF GPIO,SOUND_PIN ;INVERSE BSF GPIO,LED_PIN CLRF FLAG_REG return ;--------------------------------------------- SELF_TEST BCF GPIO,LED_PIN MOVLW D'20' ;20*100uS, 500Hz MOVWF SOUND_TEMP1 MOVLW D'100' ;100 CYCLO MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'16' ; 625Hz MOVWF SOUND_TEMP1 MOVLW D'126' ;126 CYCLO MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'12' ;833z MOVWF SOUND_TEMP1 MOVLW D'166' ;166 CYCLO MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'10' ;1000z MOVWF SOUND_TEMP1 MOVLW D'200' ;200 CYCLO MOVWF SOUND_TEMP2 CALL sound ; BSF GPIO,LED_PIN return ;--------------------------------------------- sound BCF STATUS,C RRF SOUND_TEMP1,F ;DURATION/2, 50% DUTY RATE SOUND_1 BCF GPIO,SOUND_PIN MOVF SOUND_TEMP1,W CALL LOOP_S ;100uS LOOP BSF GPIO,SOUND_PIN MOVF SOUND_TEMP1,W CALL LOOP_S ;100uS LOOP DECFSZ SOUND_TEMP2,F GOTO SOUND_1 return ;--------------------------------------------- GET_Votlage B0 BCF STATUS,RP0 ; BANK0 MOVLW B'00000001' ; AN0 MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON CALL START_ADC COMPARE0 MOVF ADRESH,W MOVWF CELL0_V ;SAVE CELL 0 VOLTAGE MOVWF ACCcLO ;SAVE (AN0) TO ACCc MOVWF ACCbLO CLRF ACCbHI MOVLW LOW_VOLTAGE MOVwF ACCaLO CLRF ACCaHI CALL D_SUB ; B - A SKPNC ;IF f < w, C= 0,SKIP ;SKIP IF LOW VOLTAGE GOTO B1 B1_1 BSF FLAG_REG,0 ;AN0 < LOW_voltage BSF FLAG_REG,7 ; LOW CELL FLAG BCF GPIO,LED_PIN B1 BCF STATUS,RP0 ; BANK0 MOVLW B'00000101' ; AN1 MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON CALL START_ADC COMPARE1 MOVF ADRESH,W MOVWF ACCbLO CLRF ACCbHI CALL D_DOUBLE ;AN1*2 MOVF ACCcLO,W MOVWF ACCaLO CLRF ACCaHI ; RESTORE AN0 FROM ACCc MOVF ACCbLO,W MOVWF ACCcLO MOVF ACCbHI,W MOVWF ACCcHI ;SAVE (AN1*2) TO ACCc CALL D_sub ;(AN1*2)-AN0 B-A MOVF ACCbLO,W MOVWF CELL1_V ;SAVE CELL 1 VOLTAGE SKPC GOTO B2_1 ;;((AN1*2)-AN0)<0 MOVLW LOW_VOLTAGE MOVwF ACCaLO CLRF ACCaHI CALL D_SUB ; B - A SKPNC ;IF f < w, C= 0,SKIP ;SKIP IF LOW VOLTAGE GOTO B2 B2_1 BSF FLAG_REG,1 BSF FLAG_REG,7 ; LOW CELL FLAG BCF GPIO,LED_PIN B2 BCF STATUS,RP0 ; BANK0 MOVLW B'00001001' ; AN2 MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON CALL START_ADC COMPARE2 MOVF ADRESH,W MOVWF ACCbLO CLRF ACCbHI CALL D_DOUBLE CALL D_DOUBLE ;AN2*4 MOVF ADRESH,W MOVWF ACCaLO CLRF ACCaHI CALL D_sub ;(AN2*4)-AN2=AN2*3 MOVF ACCcLO,W MOVWF ACCaLO MOVF ACCcHI,W MOVWF ACCaHI ;move (AN1*2) from ACCc TO ACCa CALL D_sub ;((AN2*3)-(AN1*2)) MOVF ACCbLO,W MOVWF CELL2_V ;SAVE CELL 2 VOLTAGE SKPC ; GOTO B3_1 ;((AN2*3)-(AN1*2)) <0 MOVLW LOW_VOLTAGE MOVwF ACCaLO CLRF ACCaHI CALL D_SUB ; B - A SKPNC ;IF f <= w, C= 0,SKIP ;SKIP IF LOW VOLTAGE GOTO B3 B3_1 BSF FLAG_REG,2 BSF FLAG_REG,7 ; LOW CELL FLAG BCF GPIO,LED_PIN B3 BTFSC FLAG_REG,7 ; IF CELL LOW 7=1, DON'T DETECT UNBALANCE GOTO B4 UNBAL MOVF CELL0_V,W SUBWF CELL1_V,W CALL CHECK_UNBAL MOVF CELL1_V,W SUBWF CELL2_V,W CALL CHECK_UNBAL MOVF CELL2_V,W SUBWF CELL0_V,W CALL CHECK_UNBAL B4 return ;----------------------------------------- ; CHECK_UNBAL ;IF UNBAL, BSF FLAG_REG,6 MOVWF TEMP0 BTFSS STATUS,C COMF TEMP0,F ; NEGATIVE MOVLW UNBAL_VOLTAGE SUBWF TEMP0,W ;F UNBAL_VOLTAGE return ;------------------------------------------ ; START_ADC BCF STATUS,RP0 ; BANK0 BSF ADCON0,GO ;START ADC START_ADC1 BTFSC ADCON0,GO GOTO START_ADC1 return ;------------------------------------------ ; output_audio MOVLW D'40' ; CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,0 GOTO OA_1 MOVLW D'10' ;1000z MOVWF SOUND_TEMP1 MOVLW D'200' ;200 CYCLO MOVWF SOUND_TEMP2 CALL sound ; OA_1 MOVLW D'40' ; CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,1 GOTO OA_3 MOVLW 2 MOVWF TEMP0 OA_2 MOVLW D'10' ;1000z MOVWF SOUND_TEMP1 MOVLW D'200' ;200 CYCLO MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'10' ;100 mS CALL LOOP_L ; DECFSZ TEMP0,F GOTO OA_2 OA_3 MOVLW D'40' ; CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,2 GOTO OA_5 MOVLW 3 MOVWF TEMP0 OA_4 MOVLW D'10' ;1000z MOVWF SOUND_TEMP1 MOVLW D'200' ;200 CYCLO MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'10' ;100 mS CALL LOOP_L ; DECFSZ TEMP0,F GOTO OA_4 OA_5 MOVLW D'40' ; CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,6 ; IF UNBAL 6=1, FLASH LED AND BEEP 5 GOTO OA_9 ; RETURN BTFSC FLAG_REG,7 GOTO OA_51 BCF GPIO,LED_PIN GOTO OA_53 OA_51 BSF GPIO,LED_PIN OA_53 MOVLW 5 ;5 BEEP MOVWF TEMP0 OA_6 MOVLW D'16' ;625Hz MOVWF SOUND_TEMP1 MOVLW D'126' ; MOVWF SOUND_TEMP2 CALL sound ; MOVLW D'10' ;100 mS CALL LOOP_L ; DECFSZ TEMP0,F GOTO OA_6 BTFSC FLAG_REG,7 GOTO OA_55 BSF GPIO,LED_PIN GOTO OA_57 OA_55 BCF GPIO,LED_PIN OA_57 OA_9 return ;========================================= LOOP_S ;100 uS LOOP *W MOVWF TEMP1 LOOP_S1 MOVLW D'24' ;(24*4)=96 MOVWF TEMP2 LOOP_S2 NOP DECFSZ TEMP2,1 GOTO LOOP_S2 DECFSZ TEMP1,1 GOTO LOOP_S1 return ;========================================= LOOP_L ;10 mS LOOP *W MOVWF TEMP1 LOOP_L1 MOVLW D'10' ;10 mS MOVWF TEMP2 LOOP_L2 MOVLW D'249' ;(249*4)+5=1001 MOVWF TEMP3 LOOP_L3 NOP DECFSZ TEMP3,1 GOTO LOOP_L3 DECFSZ TEMP2,1 GOTO LOOP_L2 DECFSZ TEMP1,1 GOTO LOOP_L1 RETURN ;============================================== ; ;******************************************************************* ; Double Precision Double ; ; Double : ACCb(16 bits)*2 -> ACCb(16 bits) ; (a) Load the 1st operand in location ACCb( 16 bits ) ; (b) CALL D_Double ; (c) The result is in location ACCbLO & ACCbHI ( 16 bits ) ; ; ; Revision Date: 2005-12-09 ; By: Philip Sun (aka: iLuFa) ;*******************************************************************; D_Double bcf status,c ;3,0 rlf ACCbLO,F rlf ACCbHI,F retlw 0 ;**************************************************************** ;******************************************************************* ; Double Precision Subtraction ; ; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits) ; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits ) ; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits ) ; (c) CALL D_sub ; (d) The result is in location ACCbLO & ACCbHI ( 16 bits ) ; (e) If ACCa > ACCb, Carry =0 (Status,C) ; ; Revision Date: 2005-12-12 ; By: Philip Sun (aka: iLuFa) ;*******************************************************************; D_sub movf ACCaLO,W subwf ACCbLO,F ;lsd SKPC ;f ACCb GOTO D_SUB_2 decf ACCbHI,F movf ACCaHI,W subwf ACCbHI,F ;msb return ;IF ACCa > ACCb C=0 D_SUB_2 decf ACCbHI,F movf ACCaHI,W subwf ACCbHI,F ;msb BCF STATUS,C ;ACCa > ACCb return ;**************************************************************** END