;***************************** ; PIC 16F876 UTILITY ROUTINES ;***************************** ; ; 2002 (c)Radu Constantinescu ; Released under GNU PUBLIC LICENSE ; ; Display routines, 16F87X Q=20Mhz ; display LCD 2*16 SII L1652BIJ2 ; with HD74780A00 IC or similar ; Display connected to Port B ; ; PORTB0 DATA4 ; PORTB1 DATA5 ; PORTB2 DATA6 ; PORTB3 DATA7 ; DATA0-3 - GROUND ; PORTB4 RS ; PORTB5 E ; PORTB6 - Reserved ICD ; PORTB7 - reserved ICD ; ; ; ; init_disp - initialize display ; disp_clear - clear display ; cur_h1 - cursor home line 1 ; cur_h2 - cursor home line 2 ; ; movlw LOW text ; movwf comA ; movlw HIGH text ; movwf comB ; call prt_rom - print the text in Rom (comB:comA) ; ; binbcdU8 - convert 8 bit unsigned count_1 to dis_2,dis_1 ; bcdascii8 - Convert bcd dis_2..1 in ASCII dis_4..1 ; leadzero8 - delete leading zeroes from dig_4 - dig_2 ; dispU8 - display 8 bit unsigned count_1 to dis_4..1, +1 stack level ; dispS8 - display 8 bit signed count_1 to dis_4..1, +1 stack level ; ; binbcdU32 - convert 32 bit unsigned count_4:3:2:1-->dig_5..1, 10 digits, dis_5 low nibble=MSD, +1 stack level ; bcdascii32 - Convert bcd dig_5..1 in ASCII dig_9..1 ; leadzero32 - delete leading zeroes from dig_10 - dig_2 ; ; prtram - print from RAM, string located at (IRP:W) ; send_c - send char in W to display ; ; init_usart - init serial 9600,8,N,1 ; ser_out - Output W to serial ; ser_ram - send string (IRP:W) to serial ; ; ; EE_WRITE_BYTE - Routine to write a byte to EEram - Adress in W, byte MUST be in EE_Byte ; EE_READ_BYTE - Routine to read a byte from EEram - Adress in W, byte will be delivered in W #include Bank0: MACRO bcf STATUS, RP0 bcf STATUS, RP1 ENDM Bank1: MACRO bsf STATUS, RP0 bcf STATUS, RP1 ENDM Bank2: MACRO bcf STATUS, RP0 bsf STATUS, RP1 ENDM Bank3: MACRO bsf STATUS, RP0 bsf STATUS, RP1 ENDM ;**************************** ; ;User Variables ; ;**************************** ; insert user variables here ; Utility routines variables CBLOCK 0x50 scrA: 1 ; scratch pad 0X50 scrB: 1 scrC: 1 scrD: 1 count_1:1 ; counter lsb count_2:1 count_3:1 count_4:1 ; counter msb dig_10: 1 ; display digit 10 dig_9: 1 ; display digit 9 dig_8: 1 ; display digit 8 dig_7: 1 ; display digit 7 dig_6: 1 ; display digit 6 dig_5: 1 ; display digit 5 dig_4: 1 ; display digit 4 dig_3: 1 ; display digit 3 dig_2: 1 ; display digit 2 dig_1: 1 ; display digit 1 dig_0: 1 ; end of string 0 EE_Byte:1 ; Temp var for EEProm Routines ENDC CBLOCK 0x72 ; variables for all the RAM pages comA: 1 comB: 1 comC: 1 comD: 1 ENDC ;*********************************************** ;EEprom Variables ;*********************************************** OUT0 EQU 0X0 ORG h'2100' ;EEPROM INITIAL VALUES DE 0 ;************************************************ ; insert user program here org 0 nop nop clrf STATUS call init_disp call cur_h1 movlw LOW linie1 movwf comA movlw HIGH linie1 movwf comB call prt_rom ;print the text in Rom (comB:comA) call cur_h2 movlw LOW linie2 movwf comA movlw HIGH linie2 movwf comB call prt_rom ;print the text in Rom (comB:comA) loop: goto loop ;***************************************************************************************** ; send caracter in W + 100 uS delay send_c: movwf comC swapf comC, W andlw 0xF iorlw 0x10 ;RS=1 movwf PORTB ;E=0 nop bsf PORTB,0x5;E=1 nop nop bcf PORTB,0x5;E=0 goto $+1 goto $+1 ;delay 1 uS movf comC, W andlw 0xF iorlw 0x10 ;RS=1 movwf PORTB ;E=0 nop bsf PORTB,0x5;E=1 nop nop bcf PORTB,0x5;E=0 ; delay 100 uS del_100: movlw 165 ; 165 = 100uS movwf scrA del_100A: decfsz scrA, F goto del_100A return ; send byte in W send_b: movwf comC swapf comC, W ; high nibble andlw 0xF movwf PORTB ;E=0 nop bsf PORTB,0x5;E=1 nop nop bcf PORTB,0x5;E=0 goto $+1 goto $+1 ; delay 1uS movf comC, W ; Low nibble andlw 0xF movwf PORTB ; E=0 nop bsf PORTB,0x5; E=1 nop nop bcf PORTB,0x5; E=0 return ; send nibble, low w send_n: movwf PORTB ; E=0 nop bsf PORTB,0x5 ; E=1 nop nop bcf PORTB,0x5 ; E=0 return ; print the string located at (comB:comA) in program memory prt_rom: Bank2 prt_rom1: movf comA, W ;Write the movwf EEADR ;address bytes movf comB, W movwf EEADRH bsf STATUS, RP0 ;Bank3 bsf EECON1, EEPGD ;Point to program memory bsf EECON1, RD ;start read operation nop ;required two nop's nop bcf STATUS, RP0 ;Bank2 movf EEDATA, W ;char in W andlw 0xFF ;compare 0 btfsc STATUS, Z goto prt_rom2 Bank0 call send_c ; print char in w+100uS wait incfsz comA, F goto prt_rom incf comB, F goto prt_rom prt_rom2: Bank0 return ; cursor home line 1 cur_h1: movlw 0x80 cur_h11: call send_b call del_100 return ; cursor home line 2 cur_h2: movlw 0xC0 goto cur_h11 ; delay 1 ms del_1m: movlw 0xA ; w=delayX100nS del_1mx: movwf scrB del_1mA: decfsz scrB, F goto del_1mB return del_1mB: movlw 165 movwf scrA del_1mC: decfsz scrA, F goto del_1mC goto del_1mA prt_ram: ;print from RAM, string located at (IRP:W) movwf FSR prt_ram1: movlw 0 subwf INDF, w ; compare 0 btfsc STATUS, Z return ; char = zero movf INDF, W call send_c incf FSR, F goto prt_ram1 leadzero8: ; delete leading zeroes from dig_4 - dig_2 BCF STATUS, IRP movlw .3 movwf scrA movlw LOW dig_4 goto leadzeroin leadzero32: ; delete leading zeroes from dig_10 - dig_2 BCF STATUS, IRP movlw .9 movwf scrA movlw LOW dig_10 leadzeroin: movwf FSR leadz1: movlw 0x30 ; ascii zero subwf INDF, w ; compare 0x30 btfss STATUS, Z return ; first char <>zero movlw 0x20 ; ascii space movwf INDF decf scrA, F btfsc STATUS, Z ; exit if zero return incf FSR, F goto leadz1 bcdascii32: ; Convert bcd dis_5..1 in ASCII dis_9..1 swapf dig_5, W andlw 0x0F addlw 0x30 movwf dig_10 movf dig_5, W andlw 0x0F addlw 0x30 movwf dig_9 swapf dig_4, W andlw 0x0F addlw 0x30 movwf dig_8 movf dig_4, W andlw 0x0F addlw 0x30 movwf dig_7 swapf dig_3, W andlw 0x0F addlw 0x30 movwf dig_6 movf dig_3, W andlw 0x0F addlw 0x30 movwf dig_5 bcdascii8: ; Convert bcd dis_2..1 in ASCII dis_4..1 swapf dig_2, W andlw 0x0F addlw 0x30 movwf dig_4 movf dig_2, W andlw 0x0F addlw 0x30 movwf dig_3 swapf dig_1, W andlw 0x0F addlw 0x30 movwf dig_2 movf dig_1, W andlw 0x0F addlw 0x30 movwf dig_1 return dispS8: ; display 8 bit signed count_1 to dis_4..1, +1 stack level btfss count_1,7 goto dispU8 ; disp neg 8 comf count_1, F ; complement incf count_1, F ; X(-1) call binbcdU8 ; dis2..1 bcd call bcdascii8 ; dis4..1 ascii ; leadzero and - delete leading zeroes from dig_4..2 and add the - sign BCF STATUS, IRP movlw .4 movwf scrA movlw LOW dig_4 movwf FSR leadzN1: movlw 0x30 ; ascii zero subwf INDF, w ; compare 0x30 btfss STATUS, Z goto leadzN2 ; first char <>zero, add - movlw 0x20 ; ascii space movwf INDF decf scrA, F btfsc STATUS, Z ; exit if zero return incf FSR, F goto leadzN1 leadzN2: ; dec pointer and display "-" decf FSR, F movlw "-" ; ascii - movwf INDF return return dispU8: ; display 8 bit unsigned count_1 to dis_4..1, +1 stack level call binbcdU8 call bcdascii8 call leadzero8 return binbcdU8: ; convert 8 bit unsigned count_1 to dis_2,dis_1 bcf STATUS,C ; clear the carry bit BCF STATUS, IRP ;Page zero or 1 for indirect movlw 8 movwf scrA clrf dig_1 clrf dig_2 loop8: rlf count_1,F rlf dig_1, F rlf dig_2, F ; decfsz scrA, F goto adjDEC8 RETLW 0 ; adjDEC8: movlw dig_1 movwf FSR movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD ; movlw dig_2 movwf FSR movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD goto loop8 ; binbcdU32: ; convert 32 bit unsigned count_4:3:2:1-->dig_5..1, 10 digits, ; dis_5 low nibble=MSD, +1 stack level bcf STATUS,C ; clear the carry bit BCF STATUS, IRP ;Page zero or 1 for indirect movlw .32 movwf scrA clrf dig_1 clrf dig_2 clrf dig_3 clrf dig_4 clrf dig_5 loop28: rlf count_1,F rlf count_2,F rlf count_3,F rlf count_4,F rlf dig_1, F rlf dig_2, F rlf dig_3, F rlf dig_4, F rlf dig_5, F ; decfsz scrA, F goto adjDEC RETLW 0 ; adjDEC: movlw dig_1 movwf FSR call adjBCD ; movlw dig_2 movwf FSR call adjBCD ; movlw dig_3 movwf FSR call adjBCD ; movlw dig_4 movwf FSR call adjBCD ; movlw dig_5 movwf FSR call adjBCD goto loop28 adjBCD: movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD RETLW 0 ; init display in 4 bit transfer mode init_disp: Bank0 clrf PORTB Bank1 movlw B'11000000' ; port B<0..5>=out movwf TRISB Bank0 movlw 200 ; 20ms call del_1mx movlw 0x3 call send_n movlw 50 ; 5ms call del_1mx movlw 0x3 call send_n call del_100 ; 100uS movlw 0x3 call send_n call del_100 movlw 0x2 call send_n call del_1m movlw 0x28 ; function, 4 bit data, 2 line, 5X7 call send_b call del_1m movlw 0x6 ; Entry mode set, increment, no shift call send_b call del_100 movlw 0xE ; display on, cursor on, blink off call send_b call del_100 disp_clear: movlw 0x1 ; display clear call send_b movlw 30 ; 2 ms delay to clear the display call del_1mx return linie1: DE "Display Test ",0 linie2: DE "by Radu (c)2002",0 linie3: DE " ",0 ;*************************************************************************** init_usart ; init serial banksel TXSTA ;initialize USART movlw B'10100100' ;Master mode, 8-bit, Async, High speed, TSR full movwf TXSTA movlw .129 ;9.6Kbaud @ 20MHz movwf SPBRG banksel RCSTA movlw B'10010000' ; Serial enable, 8bit, X, cont rec, xxxx movwf RCSTA banksel PORTA return ser_out ;write W to serial port btfss PIR1,TXIF ;wait for data TX Buffer goto $-1 movwf TXREG ;move data into TXREG return ser_ram: ;send from RAM, string located at (IRP:W) movwf FSR ser_ram1: movlw 0 subwf INDF, w ; compare 0 btfsc STATUS, Z return ; char = zero movf INDF, W btfss PIR1,TXIF ;wait for data TX Buffer goto $-1 movwf TXREG ;move data into TXREG incf FSR, F goto ser_ram1 ;**************************** ;EEprom routines by Tony Kubek DISABLE_IRQ MACRO LOCAL STOP_INT STOP_INT BCF INTCON,GIE ; disable global interrupt BTFSC INTCON,GIE ; check if disabled GOTO STOP_INT ; nope, try again ENDM ;+++++ ; ENABLE_IRQ enable global irq ENABLE_IRQ MACRO BSF INTCON,GIE ; enable global interrupt ENDM ; *********************************************************************** ; EE_WRITE_BYTE - Routine to write a byte to ee ram ; Adress in W, byte MUST be in EE_Byte EE_WRITE_BYTE Bank2 ; select bank2 MOVWF EEADR ; setup adress Bank0 ; MOVF EE_Byte,W ; get byte Bank2 MOVWF EEDATA ; setup byte to write BSF STATUS,RP0 ; bank3 !! BCF EECON1,EEPGD ; set to data ee ram BSF EECON1,WREN ; enable writes DISABLE_IRQ ; disable irq's MOVLW H'55' ; required sequence !! MOVWF EECON2 MOVLW H'AA' MOVWF EECON2 BSF EECON1,WR ; begin write procedure ENABLE_IRQ ; enable irq's again BCF EECON1,WREN ; disable writes ( does not affect current write cycle ) Bank0 ; reset to bank0 ; wait for the write to complete before we return BTFSS PIR2,EEIF ; wait for interrupt flag to be set GOTO $-1 ; clear interupt bit and write enable bit BCF PIR2,EEIF ;clear eewrite irq flag RETURN ; *********************************************************************** ; EE_READ_BYTE - Routine to read a byte from ee ram ; Adress in W, byte will be delivered in W EE_READ_BYTE Bank2 MOVWF EEADR ; put in adress reg. BSF STATUS,RP0 ; bank3 !! BCF EECON1,EEPGD ; set to read data memory BSF EECON1,RD ; set bit to read BCF STATUS,RP0 ; bank2 !! MOVF EEDATA,W ; move data to W Bank0 ; Reset to BANK0 ! RETURN ; and return ;************************************************************************ END