; 4-bit LCD routine.
; This is UNTESTED but should serve as an example of assembly language
; interfacing. It assumes the -RW pin is tied low and therefore the BUSY
; signal cannot be read back and delays are necessary to pace the
; command and data flows.
;
; A better and usually quicker method is to use the BUSY flag to tell
; when the LCD is responsive to new data but to implement this, another
; pin (-RW) has to be driven.
;
; It also assumes the PIC data pins are consecutive to the LCD data pins
; and PORT B is being used as the interface, this can be changed by
; editing the #defines as necessary. Other pins on PORTB are free to
; be used for other purposes.
; first lets give the pins a more maningful name to make it easier to
; read the code.
#define LCD_PORT PORTB
#define LCD_D0 PORTB,0
#define LCD_D1 PORTB,1
#define LCD_D2 PORTB,2
#define LCD_D3 PORTB,3
#define LCD_RS PORTB,4
#define LCD_EN PORTB,5
; some workspace is needed, this line would normally be part of a bigger
; cblock elsewhere in the program.
cblock 0x20
LCD_Temp
endc
; we need three routines to communicate with the LCD, one to send commands,
; one to send data and one to initialize it. Sending data and commands is
; essentially the same except for the state of the RS pin so a common routine
; is used in both cases.
; a routine to write to the LCD. Set the RS pin first then call this
; routine with the value to send in the W register.
LCD_Write
bsf LCD_EN ; start with EN = 1
movf LCD_Temp,w ; save the value in W for later
swapf LCD_Temp,w ; swap the high and low nibbles
andlw 0x0F ; only keep low nibble
bcf LCD_D0 ; clear any bits on the LCD data lines
bcf LCD_D1
bcf LCD_D2
bcf LCD_D3
iorwf LCD_PORT,f ; write high nibble to the data lines
bcf LCD_EN ; latched on falling edge of EN pin
movf LCD_Temp,w ; recover the original value
andlw 0x0F ; only keep low nibble
bsf LCD_EN ; make EN = 1 again
bcf LCD_D0 ; clear any bits on the LCD data lines
bcf LCD_D1
bcf LCD_D2
bcf LCD_D3
iorwf LCD_PORT,f ; write low nibble to the data lines
bcf LCD_EN ; latched on falling edge of EN pin
nop ; just in case EN pulse is too short
bsf LCD_EN ; disable until next time
return
; a routine to send command in W to the LCD
LCD_Cmd
bcf LCD_RS ; RS pin = 0
call LCD_Write
return
; a routine to send command in W to the LCD
LCD_Data
bsf LCD_RS
call LCD_Write
return
LCD_Init
call Delay_50mS ; in case power was just applied
movlw 0x30
call LCD_Cmd ; send command 0x30
call Delay_10mS
call LCD_Cmd ; send command 0x30
call Delay_10mS
call LCD_Cmd ; send command 0x30
call Delay_10mS
movlw 0x20 ; for 4-bit mode
call LCD_Cmd
call Delay_10mS
return