; ********************************************************************* ; NiCd fast loader ; implements delta-U off-switch ; ; Jaap Havinga 5 jun 2000 ; ; ; ********************************************************************* list p=16F84A include ; genereer config data __config _HS_OSC ; __config _RC_OSC ; RA0 = (IN) ADC comparator 0=RC < U_measure, 1 = RC > U_measure ; RA1 = (OUT) ADC reset (active HI) ; RA2 = (OUT) charge current on=1/off=0 #define ADC_COMP_BIT 0 #define ADC_RESET_BIT 1 #define CHARGE_BIT 2 #define BANK_LOW bcf STATUS,RP0 #define BANK_HIGH bsf STATUS,RP0 #define TIMER_PERIOD D'250' ; tmr0 is sinds het optreden van de irq 7 steps verder ; daarnaast zal na het laden van de nieuwe waarde de ; tmr 2 steps stilstaan. ; voor een juiste periode moet de timer value met 7+2 = 9 steps ; gecorrigeerd worden #define TIMER_CORRECTION_VALUE D'9' #define TIMERCOUNT (H'ff'-TIMER_PERIOD+TIMER_CORRECTION_VALUE) ; geeft periode tussen twee metingen aan ; (1 sec = 4000 * 250 us, 4000 = fa0h) #define MEASURE_TIME_HI H'0f' #define MEASURE_TIME_LO H'a0' ; geeft charge-periode aan in MEASURE_TIME perioden ; 2uur = 2*60*(60*1 sec) = 7200 * 1 sec, 7200 = 1C20 #define CHARGE_TIME_HI H'1C' #define CHARGE_TIME_LO H'20' #define RESET_PULSE D'4' #define STATE_CHARGE_READY 0 #define STATE_RESET_ADC 1 #define STATE_MEASURE_ADC 2 ; 30 measures with negative delta before end charge #define NEG_DELTA_COUNT D'30' ; delta is considered negative if Umax - Uactual > 1 = Umargin #define DELTA_MARGIN D'1' ; display defines #define RS_BIT 1 #define RW_BIT 2 #define E_BIT 3 ; *************** used registers ********************* TIME_MeasureLo equ H'0C' TIME_MeasureHi equ H'0D' TIME_ChargeLo equ H'0E' TIME_ChargeHi equ H'0F' MEASUREMENT equ H'10' MaxMEASUREMENT equ H'12' CURRENT_STATE equ H'14' TIME_ResetPulse equ H'15' nNegDelta equ H'16' temp equ H'17' temp1 equ H'18' temp2 equ H'19' tempHex equ H'1A' tempHexNibble equ H'1B' ; *************** Start of program ********************* ; hier starten we org 0x00 reset goto init ; *************** IRQ handler ********************* org 0x04 irq BANK_LOW CLRWDT ; eerst moeten we de waakhond uitzetten! btfss INTCON,T0IE ; was timer going off? retfie ; goodbye movlw TIMERCOUNT ; reload timer movwf TMR0; btfsc CURRENT_STATE,STATE_CHARGE_READY retfie ; not charging anymore, goodbye (do not enable irq again ) btfss CURRENT_STATE,STATE_RESET_ADC goto test_StateIsMeasurement decfsz TIME_ResetPulse,F ; reset should last a few ms goto goodbye clrf MEASUREMENT ; clear result bcf CURRENT_STATE, STATE_RESET_ADC ; reset state is over bsf CURRENT_STATE, STATE_MEASURE_ADC ; and goto measurement-state bcf PORTA,ADC_RESET_BIT ; clear reset output goto goodbye test_StateIsMeasurement btfss CURRENT_STATE,STATE_MEASURE_ADC goto dec_counters incf MEASUREMENT , F ; increment measurement counters btfsc PORTA, ADC_COMP_BIT ; Comparator says ready? goto dec_counters bcf CURRENT_STATE,STATE_MEASURE_ADC ; turn off measurementstate call Home1 movfw MEASUREMENT call Display_Hex movlw D'6' call MoveTo1 movfw MaxMEASUREMENT call Display_Hex movlw D'10' call MoveTo0 movfw TIME_ChargeHi call Display_Hex movfw TIME_ChargeLo call Display_Hex ; compare with prev. measurement movfw MaxMEASUREMENT subwf MEASUREMENT ,W ;f-w = measure - prev btfsc STATUS,C ; negative? goto no_measurement_carry addlw DELTA_MARGIN ;see if we get it positive now... btfsc STATUS,C ; negative? goto no_measurement_carry_NoMax decfsz nNegDelta,F ; yes, decrement negative delta counter goto no_NegDelta ; not ended goto Charge_Ready ; counter is 0, so stop charging no_measurement_carry movfw MEASUREMENT ; so measurement is larger, set maxValue movwf MaxMEASUREMENT no_measurement_carry_NoMax movlw NEG_DELTA_COUNT ; we want to be sure movwf nNegDelta no_NegDelta bsf PORTA,CHARGE_BIT ; set charging on goto goodbye ; leave now dec_counters movlw D'1' subwf TIME_MeasureLo, F btfsc STATUS,C goto goodbye decf TIME_MeasureHi, F btfss STATUS,Z ; should start measurement? goto goodbye movlw MEASURE_TIME_HI ; yes, first reset counters movwf TIME_MeasureHi movlw MEASURE_TIME_LO movwf TIME_MeasureLo movlw D'1' subwf TIME_ChargeLo, F btfsc STATUS,C goto no_charge_Carry decf TIME_ChargeHi, F btfsc STATUS,Z ; is charge-timeout reached? goto Charge_Timeout no_charge_Carry movlw RESET_PULSE movwf TIME_ResetPulse bsf CURRENT_STATE,STATE_RESET_ADC ; goto reset-state bsf PORTA,ADC_RESET_BIT ; set reset output bcf PORTA,CHARGE_BIT ; shut off charging goodbye bcf INTCON,T0IF ; enable irq again retfie ; goodbye Charge_Timeout call Cls call STR_TIMEOUT goto finish Charge_Ready call Cls call STR_READY finish bsf CURRENT_STATE,STATE_CHARGE_READY bcf PORTA,CHARGE_BIT ; shut off retfie ; goodbye(do not enable irq again ) ; *************** End of IRQ handler ********************* ; *************** INIT part **************** init BANK_LOW ; *************** init ports *************** clrf PORTA ; set data A op 0 clrf PORTB BANK_HIGH movlw H'1' movwf TRISA ; set A to input clrf TRISB ; set B to output BANK_LOW movlw MEASURE_TIME_HI movwf TIME_MeasureHi movlw MEASURE_TIME_LO movwf TIME_MeasureLo movlw CHARGE_TIME_HI movwf TIME_ChargeHi movlw CHARGE_TIME_LO movwf TIME_ChargeLo clrf CURRENT_STATE clrf MaxMEASUREMENT movlw NEG_DELTA_COUNT movwf nNegDelta BANK_HIGH ; *************** 16F84 initialisatie *************** ; zet de opties movlw B'11001000' ; PullUp disabled, rb0 rising edge irq, psa to wdt, rate = 0 movwf OPTION_REG BANK_LOW call InitDisplay call STR_CHARGE CLRWDT ; de waakhond uitzetten! (gaat om de 18 ms af!!) movlw TIMERCOUNT ;; initialiseer timer movwf TMR0 bsf INTCON,GIE ; enable interrupts bsf INTCON,T0IE ; enable timer 0 irq ; *************** main function *************** loop goto loop ; wait for interrupt delay40us CLRWDT movlw D'11' movwf temp1 loop40us decfsz temp1,f goto loop40us return delay4ms movlw D'100' movwf temp2 loop4ms call delay40us decfsz temp2,f goto loop4ms return WaitDisplayReady CLRWDT BANK_HIGH movlw H'f0' movwf TRISB ; set B to input BANK_LOW clrf PORTB bsf PORTB,RW_BIT bsf PORTB,E_BIT WaitLoop nop nop btfsc PORTB,7 goto WaitLoop clrf PORTB BANK_HIGH movlw H'00' movwf TRISB ; set B to output BANK_LOW return write_nibbleD andlw H'f0' iorlw h'02' movwf PORTB bsf PORTB,E_BIT nop bcf PORTB,E_BIT return write_byteD movwf temp call write_nibbleD rlf temp,f rlf temp,f rlf temp,f rlf temp,f movfw temp call write_nibbleD goto WaitDisplayReady write_nibbleC andlw H'f0' movwf PORTB bsf PORTB,E_BIT nop bcf PORTB,E_BIT return write_byteC movwf temp call write_nibbleC rlf temp,f rlf temp,f rlf temp,f rlf temp,f movfw temp call write_nibbleC goto WaitDisplayReady InitDisplay call delay4ms ; delay power up call delay4ms call delay4ms call delay4ms call delay4ms movlw H'30' ; 8 bit mode call write_nibbleC call delay4ms movlw H'30' ; 8 bit mode call write_nibbleC call delay4ms movlw H'30' ; 8 bit mode call write_nibbleC call delay4ms movlw H'20' ; 4 bit mode call write_nibbleC call delay4ms movlw H'28' ; 4 bit mode call write_byteC movlw H'08' ; display off, cursor off, call write_byteC movlw H'0e' ; display on, cursor on, blinking cursor call write_byteC movlw H'06' ; cursor moving right, no shift display call write_byteC Cls movlw H'01' ; goto write_byteC ; exit init also Home0 clrw MoveTo0 iorlw H'80' ; goto write_byteC ; Home1 clrw MoveTo1 iorlw H'C0' ; goto write_byteC ; Display_Hex movwf tempHex movwf tempHexNibble rrf tempHexNibble,f rrf tempHexNibble,f rrf tempHexNibble,f rrf tempHexNibble,f call display_hexNibble movfw tempHex movwf tempHexNibble display_hexNibble movlw h'0f' andwf tempHexNibble,f movlw D'10' subwf tempHexNibble,w ;f-w = d-10 btfsc STATUS,C goto hex_af movfw tempHexNibble iorlw H'30' goto write_byteD hex_af addlw h'41' goto write_byteD STR_CHARGE movlw A'C' call write_byteD movlw A'h' call write_byteD movlw A'a' call write_byteD movlw A'r' call write_byteD movlw A'g' call write_byteD movlw A'e' goto write_byteD STR_READY movlw A'R' call write_byteD movlw A'e' call write_byteD movlw A'a' call write_byteD movlw A'd' call write_byteD movlw A'y' goto write_byteD STR_TIMEOUT movlw A'T' call write_byteD movlw A'i' call write_byteD movlw A'm' call write_byteD movlw A'e' call write_byteD movlw A'O' goto write_byteD movlw A'u' goto write_byteD movlw A't' goto write_byteD END