LIST P=12F675,R=HEX ; ; Monitor for Li-Ion / Li-Poly Battery Packs with cell balance connector ; SUN, PU-NENG ; ; ; VERSION 3.0 (DEC/12/2005) ; BM4 ; ; 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 AN3 = cell (0+1+2+3)/4 ; ; Voltage cell 0 = AN0 ; Voltage cell 1 = (AN1*2)-AN0 ; Voltage cell 2 = (AN2*3)-(AN1*2) ; Voltage cell 3 = (AN3*4)-(AN2*3) ;============================================== ; ;---- 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' ;DEFAULT = CLEAR ; FLAG 0~3 = CELL 0~3 LOW, 5= 3 CELLS PACK, 6= UNBAL, 7= CELL LOW ; 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 CELL3_V equ 34 ; ;============================================ ;---- VARIABLES DEFINE ---- ; ;LOW_VOLTAGE EQU D'153' ; (3.0V/5.0V)*255= 153 LOW_VOLTAGE EQU D'163' ; (3.2V/5.0V)*255= 163 ;LOW_VOLTAGE EQU D'173' ; (3.4V/5.0V)*255= 173 ;UNBAL_VOLTAGE EQU D'10' ; (0.2V/5.0V)*255= 10 ; ;nominal 0.2V, actually 0.1~0.15V UNBAL_VOLTAGE EQU D'15' ; (0.3V/5.0V)*255= 15 ;UNBAL_VOLTAGE EQU D'25' ; (0.5V/5.0V)*255= 25 ;---- HARDWARE DEFINE ---- ; AN0 EQU 0 AN1 EQU 1 AN2 EQU 2 AN3 EQU 4 ;AN3 = GPIO 4 SOUND_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'00011111' ;GPIO 0~4 =input MOVWF TRISIO MOVLW B'00101111' MOVWF ANSEL ;T32, AN 0~3 ARE ANALOG BCF STATUS,RP0 ; BANK0 MOVLW B'00000001' MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON BSF GPIO,SOUND_PIN ;INVERSE CLRF FLAG_REG return ;--------------------------------------------- SELF_TEST 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 ; return ;--------------------------------------------- ;-------- (SOUND_TEMP1*100uS)= Period, ;-------- (PERIOD*SOUND_TEMP2)= Duration 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 CALL START_ADC ; BUG BUG, IF CELL3=0 COMPARE0 MOVF ADRESH,W MOVWF CELL0_V ;SAVE CELL 0 VOLTAGE MOVWF ACCcLO ;SAVE (AN0) TO ACCc MOVWF ACCbLO CLRF ACCcHI 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 ;Cell 0 < LOW_voltage BSF FLAG_REG,7 ; LOW CELL FLAG ;-------------------------------------- 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 ;----------------------------------------- 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 MOVF ACCbLO,W MOVWF ACCcLO MOVF ACCbHI,W MOVWF ACCcHI ;SAVE (AN2*3) TO ACCc 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 B4 B3_1 BSF FLAG_REG,2 BSF FLAG_REG,7 ; LOW CELL FLAG ;---------------------------------------- B4 BTFSC FLAG_REG,5 ; ONLY 3 CELLS GOTO B5_1 BCF STATUS,RP0 ; BANK0 MOVLW B'00001101' ; AN3 MOVWF ADCON0 ; LEFT JUSTIFIED,VDD,A/D ON CALL START_ADC COMPARE3 MOVF ADRESH,W SKPNZ GOTO B5 ;NO VOLTAGE , ONLY 3 CELL MOVWF ACCbLO CLRF ACCbHI CALL D_DOUBLE CALL D_DOUBLE ;AN3*4 MOVF ACCcLO,W MOVWF ACCaLO MOVF ACCcHI,W MOVWF ACCaHI ;move (AN2*3) from ACCc TO ACCa CALL D_sub ;((AN3*4)-(AN2*3)) MOVF ACCbLO,W MOVWF CELL3_V ;SAVE CELL 2 VOLTAGE SKPC ; GOTO B4_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 B8 B4_1 BSF FLAG_REG,3 BSF FLAG_REG,7 ; LOW CELL FLAG GOTO B8 ;4 Cells CHECK UBL ;----------------------------- ;--- Only 3 CellS ------------- B5 call self_test call self_test BSF FLAG_REG,5 ; ONLY 3 CELLS B5_1 BTFSC FLAG_REG,7 ; IF CELL LOW 7=1, DON'T DETECT UNBALANCE GOTO B9 UNBAL3 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 GOTO B9 ;--------------------------------- ;--- 4 CellS ---------- B8 BTFSC FLAG_REG,7 ; IF CELL LOW 7=1, DON'T DETECT UNBALANCE GOTO B9 UNBAL4 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 CELL3_V,W CALL CHECK_UNBAL MOVF CELL3_V,W SUBWF CELL0_V,W CALL CHECK_UNBAL MOVF CELL0_V,W SUBWF CELL2_V,W CALL CHECK_UNBAL MOVF CELL1_V,W SUBWF CELL3_V,W CALL CHECK_UNBAL B9 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' ;cell 0 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' ;cell 1 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' ;cell 2 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 BTFSC FLAG_REG,5 ; ONLY 3 CELLS, JUMP GOTO OA_7 MOVLW D'40' ;cell 3 CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,3 GOTO OA_7 MOVLW 4 MOVWF TEMP0 OA_6 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_6 ;--------------------------------------- OA_7 MOVLW D'40' ;UNBAL, SOUND 625Hz FOR 1 SECOND CALL LOOP_L ; CALL GET_Votlage BTFSS FLAG_REG,6 ; IF UNBAL 6=1, BEEP GOTO OA_9 ; RETURN MOVLW 5 ;5 MOVWF TEMP0 OA_8 MOVLW D'16' ;625Hz MOVWF SOUND_TEMP1 MOVLW D'125' ;16mS*125*5=1 Second MOVWF SOUND_TEMP2 CALL sound ; DECFSZ TEMP0,F GOTO OA_8 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