Example of LCD use - source JOHN BECKER - EPE PIC TUTOR

;TUT29.ASM. 
;illustrating use of Timer and LCD set up

#DEFINE PAGE0   BCF $03,5
#DEFINE PAGE1   BSF $03,5

OPTION: .EQU $01
PCL:    .EQU $02
STATUS: .EQU $03
PORTA:  .EQU $05
TRISA:  .EQU $05
PORTB:  .EQU $06
TRISB:  .EQU $06
INTCON: .EQU $0B

LOOP:   .EQU $0C        ;loop counter 1 - general
LOOPA:  .EQU $0D        ;loop counter 2 - LCD use only
CLKCNT: .EQU $0E        ;125 secs counter
STORE:  .EQU $27        ;general store
RSLINE: .EQU $2F        ;bit 4 RS line flag for LCD

W:      .EQU 0
F:      .EQU 1

        .ORG $0004
        .ORG $0005

        clrf PORTA
        clrf PORTB
        PAGE1
        clrf TRISA      ;Port A0-A4 as output
        clrf TRISB      ;Port B0-B7 as output
        movlw %00000110 ;set timer ratio 1:128
        movwf OPTION
        PAGE0
        goto SETUP      ;bypass table

TABLCD: ADDWF PCL,F     ;LCD initialisation table
        retlw %00110011 ;initialise lcd - first byte
        retlw %00110011 ;2nd byte (repeat of first)
        retlw %00110010 ;set for 4-bit operation
        retlw %00101100 ;set for 2 lines
        retlw %00000110 ;set entry mode to increment each address
        retlw %00001100 ;set display on, cursor off, blink off
        retlw %00000001 ;clear display
        retlw %00000010 ;return home, cursor & RAM to zero
                        ;end initialisation table

MESSAG: addwf PCL,F
        retlw 'R'
        retlw 'E'
        retlw 'A'
        retlw 'D'
        retlw ' '
        retlw 'E'
        retlw 'P'
        retlw 'E'

SETUP:  call PAUSIT     ;perform first 1/5th sec delay

LCDSET: clrf LOOP       ;clr LCD set-up loop
        clrf RSLINE     ;clear RS line for instruction send
LCDST2: movf LOOP,W     ;get table address
        call TABLCD     ;get set-up instruction
        call LCDOUT     ;perform it
        incf LOOP,F     ;inc loop
        btfss LOOP,3    ;has last LCD set-up instruction now been done?
        goto LCDST2     ;no
        call PAUSIT     ;yes, perform second 1/5th sec delay
                        ;to allow final LCD command to occur
                        ;(it takes longer than the rest)

LCDMSG: clrf LOOP       ;clear loop
        bsf RSLINE,4    ;set RS for data send
LCDMS2: movf LOOP,W     ;get table address
        call MESSAG     ;get message letter
        call LCDOUT     ;show it
        incf LOOP,F     ;inc loop
        btfss LOOP,3    ;has last LCD letter been sent?
        goto LCDMS2     ;no, so repeat for next one

NOMORE: goto NOMORE     ;yes, so hold here ad infinitum!

LCDOUT: movwf STORE     ;temp store data
        movlw 60        ;set minimum time between sending full bytes to
        movwf LOOPA     ;LCD - a value of 20 used to be specified but some readers seem to have
                        ; "slower" LCDs and 60 is thus suggested as suitable for use at a
			;XTAL clk of up to about 5MHz.

DELAY:  decfsz LOOPA,F  ;keep decrementing LOOPA until zero
        goto DELAY      
        call SENDIT     ;send MSB
        call SENDIT     ;send LSB
        return

SENDIT: swapf STORE,F   ;swap data nibbles
        movf STORE,W    ;get data byte
        andlw 15        ;get nibble from byte (LSB)
        iorwf RSLINE,W  ;OR the RS bit
        movwf PORTB     ;output the byte
        BSF PORTB,5     ;set E line high
        BCF PORTB,5     ;set E line low
        return

PAUSIT: movlw 5         ;set delay counter to 5
        movwf CLKCNT    ;(for 1/25th sec x 5)
        clrf INTCON     ;clear interupt flag
PAUSE:                  ;initial 1/5th sec wait before setting up LCD
        btfss INTCON,2  ;has a timer time-out been detected?
        goto PAUSE      ;no
        BCF INTCON,2    ;yes
        decfsz CLKCNT,F ;dec counter, is it zero?
        goto PAUSE      ;no
        return          ;yes

        .END            ;final line
