;------------------------------------------------------------------------------- ; FILE: Volt Meter ; AUTH: Ed's Projects ; DATE: 11/03/2017 ; DESC: Analogue input read, voltage displayed on character LCD ; ; PortD LCD data bus ; PortC, 3 enable, 2 RW, 1 RS ;------------------------------------------------------------------------------- LIST P=18F4520, R=DEC ; All numbers Decimal format unless otherwise stated. include ; Define configurations, registers, etc. CONFIG OSC = INTIO67 ; 8 MHz internal oscillator CONFIG FCMEN = OFF ; Failsafe clock monitor off CONFIG IESO = OFF ; Internal / External oscillator switchover off CONFIG PWRT = ON ; Power up timer on CONFIG BOREN = OFF ; Brown out reset off CONFIG WDT = OFF ; Watchdog timer off CONFIG MCLRE = OFF ; Master reset pin off CONFIG LPT1OSC = OFF ; Low power timer 1 off CONFIG PBADEN = OFF ; PortB 4 to 0 digital on reset CONFIG LVP = OFF ; Low voltage programming off CONFIG XINST = OFF ; Extended instruction set enabled ;------------------------------------------------------------------------------- ;-------------------------------- Variables ---------------------------------- ;------------------------------------------------------------------------------- cblock 0x000 b0_temp b0_temp2 b0_temp3 temp1 temp2 tmpctr digit1 digit2 digit3 digit4 count0 count1 bcdtmp1 bcdtmp2 arg1L arg1H arg2L arg2H result0 result1 result2 result3 R0 R1 R2 Word0 Word1 Word2 Word3 DenL DenH lptmp endc ;------------------------------------------------------------------------------- ;------------------------------ Define Symbols ------------------------------- ;------------------------------------------------------------------------------- #define LCDen LATC, 3, 1 #define LCDrw LATC, 2, 1 #define LCDrs LATC, 1, 1 ;------------------------------------------------------------------------------- ;------------------------------- Program Code -------------------------------- ;------------------------------------------------------------------------------- ORG 0x0 ; Reset Vector ORG 0x0008 ; High Priority Interrupt Vector ORG 0x0018 ; Low Priority Interrupt Vector ;------------------------------------------------------------------------------- ;-------------------------- Initialisation of Ports -------------------------- ;------------------------------------------------------------------------------- Init movlb d'15' ; Set BSR to bank 15 clrf ADCON0 ; Turn off analogue module movlw 00001111b movwf ADCON1 ; Configure all pins as digital movlw 00000111b movwf CMCON ; Turn off comparators movlw 00000001b ; Set RA0 to Input movwf TRISA, 1 clrf TRISB clrf TRISC clrf TRISD ; Set all ports as outputs clrf TRISE movlw 01110000b movwf OSCCON ; 8MHz Internal oscillator movlw 01000000b movwf OSCTUNE ; Enable PLL ; 32MHz with PLL ;------------------------------------------------------------------------------- ;------------------------------- Main Program -------------------------------- ;------------------------------------------------------------------------------- Main call LCDinit movlw "V" call LCDsend movlw "o" call LCDsend movlw "l" call LCDsend movlw "t" call LCDsend movlw "a" call LCDsend movlw "g" call LCDsend movlw "e" call LCDsend movlw " " call LCDsend movlw " " call LCDsend movlw " " call LCDsend movlw " " call LCDsend movlw " " call LCDsend movlw "V" call LCDsend loop call ADC movff ADRESL, arg1L movff ADRESH, arg1H movlw 0x01 movwf arg2H, 0 movlw 0xF4 movwf arg2L, 0 call MUL16 movff result0, Word0 movff result1, Word1 movff result2, Word2 movff result3, Word3 movlw 0xFF movwf DenL, 0 movlw 0x03 movwf DenH, 0 call Divide movff Word0, count0 movff Word1, count1 call BCD movlw 10001000b call LCDinst movf digit3, w, 0 call LCDdigit movlw "." call LCDsend movf digit2, w, 0 call LCDdigit movf digit1, w, 0 call LCDdigit call delay goto loop ;------------------------------------------------------------------------------- ;----------------------------- LCD Initialisation ---------------------------- ;------------------------------------------------------------------------------- LCDinit call d50ms ;Function Set movlw 00111000b ;8-bit mode, 2 lines, 5x7 matrix call LCDinst ;Display on / off movlw 00001100b ;Display on, Cursor off, Blink off call LCDinst ;Entry Mode Set movlw 00000110b ;Increment, Display shifted call LCDinst ;Cursor or display shift movlw 00010000b ;Display Shift call LCDinst ;Clear Screen movlw 00000001b ; Clear screen call LCDinst return ;------------------------------------------------------------------------------- ;----------------------------- LCD Character Send ---------------------------- ;------------------------------------------------------------------------------- LCDsend movlb d'15' ; Ensure BSR is FSR banking bsf LCDrs ; Data mode bcf LCDrw ; Write mode call sndt ; Send data return ;------------------------------------------------------------------------------- ;------------------------- LCD Character Digit Send -------------------------- ;------------------------------------------------------------------------------- LCDdigit movlb d'15' ; Ensure BSR is FSR banking bsf LCDrs ; Data mode bcf LCDrw ; Write mode addlw d'48' call sndt ; Send data return ;------------------------------------------------------------------------------- ;---------------------------- LCD Instruction Send --------------------------- ;------------------------------------------------------------------------------- LCDinst movlb d'15' ; Ensure BSR is FSR banking bcf LCDrs ; Instruction mode bcf LCDrw ; Write mode call sndt ; Send data call d50ms return ;------------------------------------------------------------------------------- ;--------------------------------- Bus Send --------------------------------- ;------------------------------------------------------------------------------- sndt movwf LATD, 1 ; Place into LCD bus nop bsf LCDen nop nop nop bcf LCDen goto micro100 ;------------------------------------------------------------------------------- ;------------------------------ Delay Routines ------------------------------- ;------------------------------------------------------------------------------- delay movlw d'100' ; 125ns 1 second delay movwf b0_temp3, 0 ; 125ns nop ; 125ns label_3 movlw d'40' ; 125ns movwf b0_temp2, 0 ; 125ns nop ; 125ns nop ; 125ns label_1 movlw d'249' ; 125ns movwf b0_temp, 0 ; 125ns nop ; 125ns nop ; 125ns label_2 nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns decfsz b0_temp, f, 0 ; 125ns goto label_2 ; 250ns (1us total inner loop) ; 125ns decfsz b0_temp2, f, 0 ; 125ns goto label_1 ; 250ns ; 125ns decfsz b0_temp3, f, 0 ; 125ns goto label_3 ; 250ns return d50ms movlw d'1' ; 50ms delay movwf b0_temp3, 0 goto label_3 micro100 movlw d'100' ; 100us delay movwf b0_temp, 0 label_4 nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns decfsz b0_temp, f, 0 ; 125ns goto label_4 ; 250ns (1us total inner loop) return ;------------------------------------------------------------------------------- ;---------------------------------- Analogue --------------------------------- ;------------------------------------------------------------------------------- ADC movlw 10000010b movwf ADCON2, 1 ; Set 1/32 speed, no delay movlw 00001110b movwf ADCON1, 1 ; Set RA0, AN0 analogue input movlw 00000001b movwf ADCON0, 1 ; Channel AN0, enable module bsf ADCON0, GO, 1 ; Start Reading btfsc ADCON0, GO, 1 ; Reading done? goto $-2 return ;yes done ;------------------------------------------------------------------------------- ;-------------------------- Binary to Decimal Routine ------------------------- ;------------------------------------------------------------------------------- BCD clrf digit1, 0 clrf digit2, 0 clrf digit3, 0 clrf digit4, 0 movlw d'16' ;16 bits to do movwf bcdtmp1, 0 bcf STATUS, C bitlp rlcf count0, f, 0 ;Shift msb into carry rlcf count1, f, 0 movlw LOW digit1 movwf FSR1L, 1 ;Pointer to digits movlw HIGH digit1 movwf FSR1H, 1 ;Pointer to digits movlw d'4' ;4 digits to do movwf bcdtmp2, 0 adjlp rlcf INDF1, f, 1 ;Shift digit 1 bit left movlw d'10' subwf INDF1, w, 1 ;Check and adjust for decimal overflow btfsc STATUS, C ;Postinc affects both fsrl and fsrh movwf POSTINC1, 1 btfss STATUS, C movf POSTINC1, w, 1 ;This is just to postinc, decfsz bcdtmp2, f, 0 goto adjlp decfsz bcdtmp1, f, 0 ;Next bit goto bitlp return ;------------------------------------------------------------------------------- ;----------------------------- 16 x 16 Multiply ------------------------------ ;------------------------------------------------------------------------------- MUL16 movf arg1L, w, 0 mulwf arg2L, 0 movff PRODL, result0 movff PRODH, result1 movf arg1H, w, 0 mulwf arg2H, 0 movff PRODL, result2 movff PRODH, result3 movf arg1L, w, 0 mulwf arg2H, 0 movf PRODL, w, 1 addwf result1, f, 0 movf PRODH, w, 1 addwfc result2, f, 0 clrf WREG, 1 addwfc result3, f, 0 movf arg1H, w, 0 mulwf arg2L, 0 movf PRODL, w, 1 addwf result1, f, 0 movf PRODH, w, 1 addwfc result2, f, 0 clrf WREG, 1 addwfc result3, f, 0 return ;------------------------------------------------------------------------------- ;------------------------------- 32 / 16 Divide ------------------------------ ;------------------------------------------------------------------------------- Divide clrf R0 clrf R1 clrf R2 movlw d'32' ; 32 loops for 32-bit movwf lptmp Div_2 bcf STATUS, C rlcf Word0, f, 0 rlcf Word1, f, 0 rlcf Word2, f, 0 rlcf Word3, f, 0 rlcf R2, f, 0 rlcf R1, f, 0 rlcf R0, f, 0 movf DenL, w, 0 subwf R2, f, 0 movf DenH, w, 0 subwfb R1, w, 0 bc Div_4 tstfsz R0, 0 goto Div_3 movf DenL, w, 0 addwf R2, f, 0 goto Div_5 Div_3 decf R0, f, 0 Div_4 movwf R1, 0 bsf Word0, 0, 0 Div_5 decfsz lptmp, f, 0 goto Div_2 ; Go do next loop return ; Finished our divide routine end