ON 20030102@2:28:12 PM at page: http://www.piclist.com/techref/io/lcd/pic.htm JMN-EFP-786 James Newton added 'reply ' ON 20030102@2:28:49 PM at page: http://www.piclist.com/techref/io/lcd/pic.htm JMN-EFP-786 James Newton added 'reply ' ON 20030102@3:03:17 PM at page: http://www.piclist.com/techref/io/lcd/pic.htm JMN-EFP-786 James Newton added 'reply ' ON 20030102@3:30:23 PM at page: http://www.piclist.com/techref/io/lcd/pic.htm JMN-EFP-786 James Newton added 'reply The delay depends on the LCD.' ON 20030117@7:28:06 AM at page: http://piclist.com/techref/io/lcd/pic.htm JMN-EFP-786 James Newton published post 37638.1373032407 a.borowski@student.qut.edu.au shares this code:
http://alborowski.tk
Here's a driver for a standard 16 char by 2 line LCD that I wrote.
The driver sets the LCD up for 4 bit mode, and is write only.
Hence only 6 I/O pins are used. Data lines 4-7 go to pins A0-A4,
and the Register Select and Enable lines can be chosen by the user
as long as they are on port B by saying something like
LCDEnable equ 3 ; The LCD enable pin on Port B
LCDRS equ 4; The LCD R/S pins on Port B
NOTE: This code presently uses a 14.7456 mhz crystal. To use a differeny xtal,
use the PIClist delay code generator to change the values of the delays. The
delay times are not that critical.
To use this code, firstly set the relevent TRIS bits, then initialise the LCD:
CALL LONGDLY
CALL LCDFUN ; sets the LCD's function to 4 bit, 2 line, 5x7 font
CALL LONGDLY
CALL LCDDISP ; Turns on the display and cursor
CALL LONGDLY
CALL LCDENT ; sets auto increment right after write (like a typewriter)
CALL LCDCLR
You know the LCD is initialized when iot is totally blank. If you get the one row
solid black and the other clear, the LCD has not been initialised properly.
Now, there are 2 ways to write to the LCD. Firstly, you can use the LCDChar method. This
is nice because it automatcally word wraps the text, and prevents you writing to non-
visible memory. For instance:
movlw "A"
movwf LCDByte
CALL LCDCHAR
To write different commands to the LCD, such as different function select bytes,
set the relevent RS bit, put the data in LCDByte, then call LCDBYTE. This is only for the LCD gurus!
To change the address, call LCDADD
eg to go to address 3,
movlw
movwf LCDadd
CALL LCDADD
To clear the LCD, CALL LCDCLR.
To 'backspace', CALL LCDBACKSPACE
If you need a hand, email me @ a.borowski@student.qut.edu.au
or visit my website at http://www.alborowski.tk
LCDADD ; makes LCDAdd the current LCD Address
nop
BCF PORTB,LCDRS
movf LCDAdd, 0
movwf LCDByte
bsf LCDByte, 7
CALL LCDBYTE
bsf PORTB,LCDRS
nop
nop
RETURN
LCDENT ; Entry Mode set - currently set to move cursor to right after each write
nop
BCF PORTB, LCDRS
movlw b'00000110'
movwf LCDByte
CALL LCDBYTE
BSF PORTB,LCDRS
nop
nop
RETURN
LCDDISP ; turns on display and cursor
nop
BCF PORTB,LCDRS
movlw b'00001110'
movwf LCDByte
CALL LCDBYTE
BSF PORTB,LCDRS
nop
nop
RETURN
LCDFUN ; sets up the LCD function byte, for 4 bit control, 2 lines, standard font
nop
movlw d'2'
movwf nibToSend
BCF PORTB, LCDRS ; we're sending a command, so R/S must be lo
CALL SENDNIB ; due to 4 bit operation, we have to resend the first nibble
CALL SHORTDLY
movlw b'00101000'
movwf LCDByte
CALL LCDBYTE
BSF PORTB, LCDRS
nop
nop
RETURN
LCDCLR ; clears the entire display
clrf LCDAdd
nop
movlw d'1'
movwf LCDByte
BCF PORTB, LCDRS ; 'cause we are doing a command, set the R/S line lo
CALL LCDBYTE ; writes LCDByte to the LCD
CALL LONGDLY ; Clearing the LCD takes ages, so a larger delay is needed
bsf PORTB, LCDRS ; set the R/S line, ready for characters
RETURN
LCDCHAR
;use this for displaying characters only, NOT control chars
;keeps track of cursor colation, and word wraps if necessary
movf LCDAdd, 0
sublw h'50'
btfsc STATUS, Z
RETURN
CALL LCDBYTE
incf LCDAdd, 1
; check if we have hit the end of the top line
movlw d'16'
subwf LCDAdd, 0
btfsc STATUS, Z ; skip if not zero
GOTO LCDLINE2 ; must go to new line
RETURN
LCDLINE2
; here we must go to the new line
movlw b'01000000'
movwf LCDAdd
CALL LCDADD
RETURN
LCDBYTE; sends a byte to the LCD, in 4bit fashion
; responsible for breaking up the byte to send into high and low nibbles
; and dumps them to LCD
;NOT responsible for the status of the LCDRS line, nor the major delays
; IN: LCDByte - distructive OUT: hiByte, loByte
clrf hiByte ; clears the vars, to prevent bugs
clrf loByte
bcf STATUS,0 ; get rif of any carry which could screw up the bitshifts
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
rlf LCDByte, 1
rlf hiByte
movf LCDByte, 0
movwf loByte
swapf loByte, 1
movf hiByte,0
movwf nibToSend
CALL SENDNIB
movf loByte,0
movwf nibToSend
CALL SENDNIB
CALL SHORTDLY ; blocks until most instructions are done
RETURN
SENDNIB; responsible for sending nibble commands to the LCD.
;IN: nibToSend - non-distructive
clrf W ; clears W
movf nibToSend, 0
movwf PORTA
nop
bsf PORTB, LCDEnable; pulse the LCD Enable high
nop
nop
bcf PORTB, LCDEnable ; lower LCD Enable
nop
nop
RETURN
BIN2BHF
; this command wil encode a byte into bastard hex format. In: BIN Out: BHF1,BHF2
clrw
clrf BHF1
clrf BHF2
bcf STATUS,0 ; get rid of any carry that could screw up the bitshift
rrf BIN,1
rrf BHF2,1
rrf BIN,1
rrf BHF2,1
rrf BIN,1
rrf BHF2,1
rrf BIN,1
rrf BHF2,1
swapf BHF2,1 ; fix up annoying bug
movf BIN, 0
movwf BHF1 ; put BHF nibble in place
;Now, to enocde in ASCII
movf BHF1, 0; put BHF1 into W for debugging
movf BHF2,0 ; put BHF2 into W for debugging
movlw d'10' ; put 10 in W
subwf BHF1, 0
clrw ; W is cleared
btfsc STATUS,0 ; test if we have a number or a letter - next command is skipped if we have a number
addlw d'39'
addlw d'48' ; subtract 10 for hex
addwf BHF1,1
movf BHF1,0 ; put BHF1 in W for debugging
;OK, BHF 1 is encoded
bcf STATUS,0 ; clear any carry (as if that could make a difference)
clrw ; Wipe W
movf BHF2,0 ; put BHF2 into W for debugging
movlw d'10' ; put 10 in W
subwf BHF2, 0
clrw ; W is cleared
btfsc STATUS,0 ; test if we have a number or a letter - next command is skipped if we have a number
addlw d'39'
addlw d'48' ; subtract 10 for hex
addwf BHF2,1
movf BHF2,0 ; put BHF2 in W for debugging
RETURN
SHORTDLY ; around 50us
;217 cycles
movlw 0x48
movwf d1
SHORTDLY_0
decfsz d1, f
goto SHORTDLY_0
;4 cycles (including call)
return
LONGDLY ; 25ms delay
;92153 cycles
movlw 0xFE
movwf d1
movlw 0x48
movwf d2
LONGDLY_0
decfsz d1, f
goto $+2
decfsz d2, f
goto LONGDLY_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
return
LCDBACKSPACE ; acts like a backspace
movf LCDAdd,0
andlw b'11111111'
btfsc STATUS, Z ; skip if not zero
RETURN ; already at end, so ignore backspace
sublw h'40'
btfsc STATUS, Z ; skip if at start of 2nd line
GOTO LCDBSTARTBOTLINE ; correct for moveing up to new line
decf LCDAdd, 1;
CALL LCDADD ; move back one
movlw d'32' ; wipe the current char
movwf LCDByte
CALL LCDBYTE
CALL LCDADD
RETURN
LCDBSTARTBOTLINE ; correct for moveing up to new line
movlw d'15'
movwf LCDAdd
CALL LCDADD ; put us at 15
movlw d'32'
movwf LCDByte
CALL LCDBYTE
RETURN
|Delete 'P-' before: '' but after: 'sarigat@hotmail.com
asks: " anyone know how to interface a 18F452
to a 16x2 LCD display "
|Delete 'P-' before: '' but after: '