;******************************************************************** ; voltage meter program ; measure voltage on AN3 and AN4 ; supports maximum 8 digits display on a LCD display. ; for PIC16F88 Ver 0.1 (11 Nov 2009) MM ;******************************************************************** ; LIST P=PIC16F88 INCLUDE "P16F88.INC" __CONFIG _CONFIG1,_CP_OFF &_PWRTE_OFF &_WDT_OFF &_INTRC_IO &_BODEN_ON &_LVP_OFF &_CPD_OFF &_DEBUG_OFF ; ; ;**************************************************** ; Define Constant or Work ;**************************************************** ; BYTE0 EQU 20H ;Counter 0 BYTE1 EQU 21H ;Counter 1 BYTE2 EQU 22H ;Counter 2 DPDT EQU 23H ;LCD output data DIGIT12 EQU 24H ;Digit12 DIGIT34 EQU 25H ;Digit34 DIGIT56 EQU 26H ;Digit56 DIGIT78 EQU 27H ;Digit78 CNT1 EQU 28H ;Timer counter CNT2 EQU 29H CNT3 EQU 2AH CNT4 EQU 2BH WORK1 EQU 2CH ;work LPCNT1 EQU 2DH ;Loop Counter LPCNT2 EQU 2EH ;Loop Counter OVRFLW EQU 2FH ;Over Flow Flag SHIFT EQU 30H ;Shift counter ;CF EQU 31H ; TEMP EQU 32H ;tempolary work ZFLG EQU 33H ;0:not zero flag, 1:flag for the tenth's place (0 or 5) ; ;******************************** ; Jumping Vector ;******************************** ; ORG 0 GOTO MAIN ; ORG 04H GOTO INTPROC INTPROC RETURN ORG 08H ;******************************** ; Main Routine ;******************************** MAIN BCF INTCON,GIE ;Interrupt Disable CALL PORT_INI ;Port A,B initialize CALL LCD_INI ;Reset LCD ;**** MAIN LOOP ***** MAINLP CALL MES3 ;measure AN3 CALL CONVRT ;Binary to BCD CALL LCD_CLR ;clear display ; MOVLW "+" ; CALL LCD_DATA CALL DISP ;Display data AN3 CALL MES4 ;measure AN4 CALL CONVRT ;Binary to BCD MOVLW 0C0H ;Set to top of 2nd Line CALL LCD_CMD ; MOVLW "-" ; CALL LCD_DATA CALL DISP ;Display data AN4 CALL TIME200M GOTO MAINLP ; ; ;*********** SUBROUTINES *********************************** ; ;***************************************** ; Measure voltage ;***************************************** ; MES3 MOVLW 099H ;AN3 MOVWF ADCON0 ; CALL TIME100 ;wait BSF ADCON0,2 ;GO! WAD3 BTFSC ADCON0,2 ;test GO/DONE flag GOTO WAD3 ;wait if flag is not cleared BSF STATUS,RP0 ;Set page 1 MOVF ADRESL,W ; BCF STATUS,RP0 ;Set Page 0 MOVWF BYTE0 ; MOVF ADRESH,W ; MOVWF BYTE1 ; CLRF BYTE2 ; RETURN ; MES4 MOVLW 0A1H ;AN4 MOVWF ADCON0 ; CALL TIME100 ;wait BSF ADCON0,2 ;GO! WAD4 BTFSC ADCON0,2 ;test GO/DONE flag GOTO WAD4 ;wait if flag is not cleared BSF STATUS,RP0 ;Set page 1 MOVF ADRESL,W ; BCF STATUS,RP0 ;Set Page 0 MOVWF BYTE0 ; MOVF ADRESH,W ; MOVWF BYTE1 ; CLRF BYTE2 ; RETURN ; ;************************************ ; Convert Binay to BCD ;************************************ CONVRT BCF STATUS,C ;reset carry BCF ZFLG,1 RRF BYTE2,F RRF BYTE1,F RRF BYTE0,F BTFSS STATUS,C BSF ZFLG,1 ; BCF STATUS,C ;reset carry MOVLW 018H ;Shift bit counter MOVWF SHIFT ;shift 32 times CLRF DIGIT12 ;clear BCD CLRF DIGIT34 CLRF DIGIT56 CLRF DIGIT78 LOOP RLF BYTE0,F ;shift BYTE to DIGIT RLF BYTE1,F RLF BYTE2,F RLF DIGIT12,F RLF DIGIT34,F RLF DIGIT56,F RLF DIGIT78,F DECFSZ SHIFT,F ;end check GOTO ADJST ;adjust to BCD RETURN ADJST MOVF DIGIT12,W ;DIGIT12 adjust TO BCD CALL ADJBCD MOVWF DIGIT12 MOVF DIGIT34,W ;DIGIT34 adjust to BCD CALL ADJBCD MOVWF DIGIT34 MOVF DIGIT56,W ;DIGIT56 adjust to BCD CALL ADJBCD MOVWF DIGIT56 MOVF DIGIT78,W ;DIGIT78 adjust to BCD CALL ADJBCD MOVWF DIGIT78 GOTO LOOP ;**** Each digit adjust to BCD **** ADJBCD MOVWF WORK1 ;save MOVLW 3 ;W+3 ADDWF WORK1,W MOVWF TEMP BTFSC TEMP,3 ;Test W+3>7 MOVWF WORK1 ;>7 then W+3 else W MOVLW 030H ;W+30 ADDWF WORK1,W MOVWF TEMP BTFSC TEMP,7 ;Test W+30>7* MOVWF WORK1 ;>70 then W+30 else W MOVF WORK1,W RETURN ; ;****************************************** ; Display 8 digits with zero supress ; and display dumy "o" by gate time ; Display "k" by prescaler ;***************************************** DISP BCF ZFLG,0 ;reset zero flag ; MOVF DIGIT78,W ; CALL DISP_D ;display 1,2 digits ; MOVF DIGIT56,W ; CALL DISP_D ;display 3,4 digits MOVF DIGIT34,W CALL DISP_D ;display 5,6 digits MOVF DIGIT12,W CALL DISP_D ;display 7,8 digits ; MOVLW "." CALL LCD_DATA ; MOVLW "0" BTFSS ZFLG,1 MOVLW "5" CALL LCD_DATA ; ; MOVF DIGITm34,W ; CALL DISP_D ;display 7,8 digits ; ; MOVLW " " ;display mV ; CALL LCD_DATA MOVLW "m" CALL LCD_DATA MOVLW "A" CALL LCD_DATA RETURN ;**** Display 1 byte Data(2 digits) ***** DISP_D MOVWF WORK1 ;save MOVF WORK1,W ;get 1,2digit SWAPF WORK1,W ;upper digit ANDLW 0FH ; MOVWF TEMP ;save BTFSS ZFLG,0 ;check zero flag CALL ZEROSUP ;zero supress MOVF TEMP,W SUBLW 0FH ;Check blank BTFSS STATUS,Z GOTO NUM1 ;not blank MOVLW 020H ;blank data GOTO DISP1 NUM1 MOVF TEMP,W ;restore IORLW 030H ;convert to ASCII DISP1 CALL LCD_DATA MOVF WORK1,W ; ANDLW 0FH ;lower digit MOVWF TEMP ;save BTFSS ZFLG,0 CALL ZEROSUP ;zero supress MOVF TEMP,W SUBLW 0FH BTFSS STATUS,Z ;check blank data GOTO NUM2 MOVLW 020H GOTO DISP2 NUM2 MOVF TEMP,W IORLW 030H ;change to ASCII code DISP2 CALL LCD_DATA RETURN ;**** Check zero subroutine **** ZEROSUP ANDLW 0FH ;check zero BTFSS STATUS,Z GOTO ZEND ;not zero MOVLW 0FH MOVWF TEMP ;set blank BCF ZFLG,0 ;zero flag off RETURN ZEND BSF ZFLG,0 ;not zero flag on MOVF TEMP,W RETURN ;*************************************************** ; LCD control routines ;*************************************************** ;**** LCD Data Write **** LCD_DATA MOVWF DPDT ;save dat ANDLW 0F0H ;mask lower MOVWF PORTB BCF PORTA,1 ;R/W BSF PORTA,2 ;RS high BSF PORTA,0 ;E high BCF PORTA,0 ;E low SWAPF DPDT,W ;get data lower ANDLW 0F0H MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL LCD_BUSY RETURN ;**** LCD command out ***** LCD_CMD MOVWF DPDT ;save dat ANDLW 0F0H ;mask lower MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS low BSF PORTA,0 ;E high BCF PORTA,0 ;E low SWAPF DPDT,W ;get data lower ANDLW 0F0H MOVWF PORTB BSF PORTA,0 BCF PORTA,0 CALL LCD_BUSY RETURN ;**** LCD Display Clear **** LCD_CLR MOVLW 01H ;clear command CALL LCD_CMD RETURN ;**** Initialize ***** LCD_INI CALL TIME5M ;wait MOVLW 030H ;Function set 8bits MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME5M ;wait MOVLW 030H ;Function reset 8bits MOVWF PORTB BCF PORTA,1 ;R/W BCF PORTA,2 ;RS BSF PORTA,0 ;E high BCF PORTA,0 ;E low CALL TIME100 MOVLW 030H ;Function reset 8bits MOVWF PORTB BCF PORTA,1 BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 MOVLW 020H ;Function set 4bits mode MOVWF PORTB ;under the 8bits mode BCF PORTA,1 BCF PORTA,2 BSF PORTA,0 BCF PORTA,0 CALL TIME100 ;From here 4bits mode MOVLW 02CH ;function DL=0 4bit mode CALL LCD_CMD MOVLW 08H ;Display off D=C=B=0 CALL LCD_CMD MOVLW 0CH ;Display on D=1 C=B=0 CALL LCD_CMD MOVLW 06H ;Entry I/D=1 S=0 CALL LCD_CMD RETURN ;**** LCD Busy Check ************ LCD_BUSY CLRF DPDT BSF STATUS,RP0 ;Bank 1 BSF OPTION_REG,7 ;Turn off PORTB pull up MOVLW 0FEH ;PORTB input MOVWF TRISB BCF STATUS,RP0 ;Bank 0 BCF PORTA,2 ;RS low BSF PORTA,1 ;R/W high BSF PORTA,0 ;E high MOVF PORTB,W ;get upper BCF PORTA,0 ;E low ANDLW 0F0H ;Mask out lower MOVWF DPDT BSF PORTA,0 ;E high SWAPF PORTB,W ;get lower BCF PORTA,0 ;E low ANDLW 0FH ;Mask out upper IORWF DPDT,F ;upper+lower BTFSC DPDT,7 ;BUSY flag check GOTO LCD_BUSY ;retry BCF PORTA,1 ;R/W low BSF STATUS,RP0 ;Bank 1 MOVLW 0EH ;RB1,2,3 input MOVWF TRISB ;PORTB BCF STATUS,RP0 ;Bank 0 RETURN ;************************************ ; PORT A & B Initialize Routine ;************************************ PORT_INI BSF STATUS,RP0 ;Set page 1 BSF OSCCON,IRCF0 BSF OSCCON,IRCF1 BSF OSCCON,IRCF2 ; set internal osc to 8MHz MOVLW 18H ;only AN3,4 analog input MOVWF ANSEL ;set analog port MOVLW 0C0H ;right justified, clk divided by 2, ref is VDD-VSS MOVWF ADCON1 ;set AD ctrl reg.1 MOVLW 0EH ;only RB1,2,3 input MOVWF TRISB ;PortB set MOVLW 018H ;only RA3,4 input MOVWF TRISA ;PortA set MOVLW 057H ;OPTION set MOVWF OPTION_REG ;for TMR0 BCF STATUS,RP0 ;Set Page 0 CLRF PORTB ;all clear RETURN ;********************************* ; Timer Routine ; TIME10 :10usec ; TIME100 :100usec ; TIME1M :1msec ; TIME5M :5msec ;********************************* TIME100 ;100usec MOVLW 9H MOVWF CNT1 T_LP1 CALL TIME10 ;2+(25+3)*9-1=253 DECFSZ CNT1,F GOTO T_LP1 RETURN ;254*0.4=100usec(about) TIME10 ;10usec MOVLW 7H MOVWF CNT2 T_LP2 DECFSZ CNT2,F ;2+3*7-1=22 GOTO T_LP2 RETURN ;22+1=23 TIME1M ;1msec(about) MOVLW 0AH MOVWF CNT3 T_LP3 CALL TIME100 ;2+(254+3)*10-1=2541 DECFSZ CNT3,F GOTO T_LP3 RETURN ;2542 TIME5M ;5msec(about) MOVLW 3BH MOVWF CNT4 T_LP4 CALL TIME100 ;2+(254+3)*59-1=15164 DECFSZ CNT4,F GOTO T_LP4 RETURN ;15165 TIME200M ;200msec(about) MOVLW 28H MOVWF CNT3 T_LP5 CALL TIME5M ; DECFSZ CNT3,F GOTO T_LP5 RETURN ; END