100% found this document useful (1 vote)
195 views20 pages

LCD 16X2 Asm

This program displays text messages on two lines of an LCD module. It initializes the LCD, then displays a message on the first line by reading characters from a text table. It moves the cursor to the second line and displays another message from a second table. The program then enters a loop to leave the display as-is. It introduces the 'goto $+2' command, which jumps two instructions ahead, allowing more efficient looping than a 'goto' followed by a 'nop'. The program also includes several LCD subroutines to simplify operations like moving the cursor, sending commands, and displaying characters.

Uploaded by

Eduardo FP
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
195 views20 pages

LCD 16X2 Asm

This program displays text messages on two lines of an LCD module. It initializes the LCD, then displays a message on the first line by reading characters from a text table. It moves the cursor to the second line and displays another message from a second table. The program then enters a loop to leave the display as-is. It introduces the 'goto $+2' command, which jumps two instructions ahead, allowing more efficient looping than a 'goto' followed by a 'nop'. The program also includes several LCD subroutines to simplify operations like moving the cursor, sending commands, and displaying characters.

Uploaded by

Eduardo FP
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 20

PIC Tutorial Three - LCD Modules

For the first parts of this tutorial you require the Main Board and the LCD Board, the
later parts will also use the Switch Board, as written the tutorials use the LCD Board on
PortA and the Switch Board on PortB. Although the hardware diagram shows a 2x16
LCD, other sizes can be used, I've tested it with a 2x16, 2x20, and 2x40 - all worked
equally well. The intention is to develop a useful set of LCD routines, these will be used
in the later parts of the tutorials to display various information.
Download zipped tutorial files.
LCD Command Control Codes
Command

Binary

Hex

D7

D6

D5

D4

D3

D2

D1

D0

Clear Display

01

Display and Cursor


Home

02 or 03

Character Entry Mode

I/D

01 to 07

Display On/Off and


Cursor

08 to 0F

Display/Cursor Shift

D/C

R/L

10 to 1F

Function Set

8/4

2/1

10/7

20 to 3F

Set CGRAM Address

40 to 7F

Set Display Address

80 to FF

I/D: 1=Increment*
1=Display Shift
S:
On
D: 1=Display On
1=Cursor
U:
Underline On
1=Cursor Blink
B:
On
D/C
1=Display Shift
:

0=Decrement
0=Display Shift
off*
0=Display Off*
0=Cursor
Underline Off*
0=Cursor Blink
Off*
0=Cursor Move

R/L: 1=Right Shift


8/4: 1=8 bit interface*
2/1: 1=2 line mode
10/7: 1=5x10 dot format
*=initialisation
setting

0=Left Shift
0=4 bit
interface
0=1 line mode*
0=5x7 dot
format*
x=don't care

This table shows the command codes for the LCD module, it was taken from an
excellent LCD tutorial that was published in the UK magazine 'Everyday
Practical Electronics' February 1997 - it can be downloaded as a PDF file from
the EPE website. The following routines are an amalgamation of a number of
routines from various sources (including the previously mentioned tutorial), plus
various parts of my own, the result is a set of reliable, easy to use, routines
which work well (at least in my opinion!).

Tutorial 3.1 - requires Main Board and LCD Board.


This program displays a text message on the LCD module, it consists mostly of
subroutines for using the LCD module.
;LCD text demo - 4 bit mode
;Nigel Goodwin 2002
using
chip

LIST

p=16F628

;tell assembler what chip we are

include "P16F628.inc"

ERRORLEVEL
0,
messages
__config 0x3D18
(oscillator type etc.)

registers

-302

;suppress bank selection


;sets the configuration settings

cblock 0x20

;start of general purpose

count
count1
counta
countb
tmp1
tmp2
templcd

mode
endc
LCD_PORT
LCD_TRIS
LCD_RS
LCD_RW
LCD_E

;include the defaults for the

;used in looping routines


;used in delay routine
;used in delay routine
;used in delay routine
;temporary storage
;temp store for 4 bit

templcd2

Equ
Equ
Equ
Equ
Equ

PORTA
TRISA
0x04
0x06
0x07

org

0x0000

;LCD handshake lines

movlw
0x07
movwf
CMCON
(make it like a 16F84)
Initialise

clrf
clrf
clrf

count
PORTA
PORTB

SetPorts

bsf
movlw
movwf
bcf

STATUS,
0x00
LCD_TRIS
STATUS,

call

Delay100

;turn comparators off

RP0

;select bank 1
;make all pins outputs

RP0

;select bank 0
;wait for LCD to settle

zero
Message
text table

NextMessage
column
zero
Message2
text table

call

LCD_Init

;setup LCD

clrf

count

;set counter register to

movf
call

count, w
Text

;put counter value in W


;get a character from the

xorlw
btfsc
goto
call
call
incf
goto

0x00
STATUS, Z
NextMessage
LCD_Char
Delay255
count, f
Message

;is it a zero?

call

LCD_Line2

;move to 2nd row, first

clrf

count

;set counter register to

movf
call

count, w
Text2

;put counter value in W


;get a character from the

xorlw
btfsc
goto
call
incf
goto

0x00
STATUS, Z
EndMessage
LCD_Char
count, f
Message2

;is it a zero?

goto

Stop

;endless loop

EndMessage
Stop

;Subroutines and text tables


;LCD routines
;Initialise LCD
LCD_Init
movlw
call

0x20
LCD_Cmd

;Set 4 bit mode

movlw
call

0x28
LCD_Cmd

;Set display shift

movlw

0x06

;Set display character

call

LCD_Cmd

movlw

0x0d

call

LCD_Cmd

call

LCD_Clr

retlw

0x00

mode

cursor command

;Set display on/off and

;clear display

; command set routine


LCD_Cmd
movwf
swapf
andlw
movwf
bcf
call

templcd
templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e

;send upper nibble


;clear upper 4 bits of W
;RS line to 0
;Pulse the E line high

movf
andlw
movwf
bcf
call
call
retlw

templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
Delay5
0x00

addlw
movwf
swapf
andlw
movwf
bsf
call

0x30
templcd
templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e

movf
andlw
movwf
bsf
call
call
retlw

templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
Delay5
0x00

;send lower nibble


;clear upper 4 bits of W

movlw

0x80

;move to 1st row, first

call
retlw

LCD_Cmd
0x00

LCD_Line2
column

movlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_Line1W
W

addlw

0x80

call
retlw

LCD_Cmd
0x00

addlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_CharD
LCD_Char

LCD_Line1
column

LCD_Line2W
W

LCD_CurOn
movlw
cursor command
call
retlw

0x0d

LCD_CurOff
movlw
cursor command
call

0x0c

;send lower nibble


;clear upper 4 bits of W
;RS line to 0
;Pulse the E line high

;send upper nibble


;clear upper 4 bits of W
;RS line to 1
;Pulse the E line high

;RS line to 1
;Pulse the E line high

;move to 2nd row, first

;move to 1st row, column

;move to 2nd row, column

;Set display on/off and

LCD_Cmd
0x00

LCD_Cmd

;Set display on/off and

retlw

0x00

LCD_Clr

movlw
call
retlw

0x01
LCD_Cmd
0x00

LCD_HEX

movwf
swapf
andlw
call
call
movf
andlw
call
call
retlw

tmp1
tmp1,
w
0x0f
HEX_Table
LCD_Char
tmp1, w
0x0f
HEX_Table
LCD_Char
0x00

Delay255

movlw
goto
movlw
goto
movlw
goto
movlw
goto
movlw
movwf
movlw
movwf
movlw
movwf

0xff
d0
d'100'
d0
d'50'
d0
d'20'
d0
0x05
count1
0xC7
counta
0x01
countb

decfsz
goto
decfsz
goto

counta, f
$+2
countb, f
Delay_0

Delay100
Delay50
Delay20
Delay5
d0
d1

Delay_0

;Clear display

;delay 255 mS
;delay 100mS
;delay 50mS
;delay 20mS
;delay 5.000 ms (4 MHz clock)
;delay 1mS

decfsz count1 ,f
goto
d1
retlw
0x00
Pulse_e

bsf
nop
bcf
retlw

LCD_PORT, LCD_E
LCD_PORT, LCD_E
0x00

;end of LCD routines


HEX_Table

ADDWF
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW

PCL
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x41
0x42

, f

RETLW
RETLW
RETLW
RETLW

0x43
0x44
0x45
0x46

Text

addwf
retlw
retlw
retlw
retlw
retlw
retlw

PCL, f
'H'
'e'
'l'
'l'
'o'
0x00

Text2

ADDWF
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW

PCL, f
'R'
'e'
'a'
'd'
'y'
'.'
'.'
'.'
0x00

end

As usual, first we need to set things up, after the normal variable declarations and
port setting we reach 'call LCD_Init', this sets up the LCD module. It first waits for
100mS to give the module plenty of time to settle down, we then set it to 4 bit mode
(0x20) and set the various options how we want them - in this case, Display Shift is On
(0x28), Character Entry Mode is Increment (0x06), and Block Cursor On (0x0D). Once
the LCD is setup, we can then start to send data to it, this is read from a table, exactly
the same as the LED sequencer in the earlier tutorials - except this time we send the data
to the LCD module (using LCD_Char) and use a 0x00 to mark the end of the table, thus
removing the need to maintain a count of the characters printed. Once the first line is
displayed we then sent a command to move to the second line (using call LCD_Line2),
and then print the second line from another table. After that we enter an endless loop to
leave the display as it is.
This program introduces a new use of the 'goto' command, 'goto $+2' - '$' is an
MPASM arithmetic operator, and uses the current value of the program counter, so 'goto
$+2' means jump to the line after the next one - 'goto $+1' jumps to the next line, and
may seem pretty useless (as the program was going to be there next anyway), but it can
be extremely useful. A program branch instruction (like goto) uses two instruction
cycles, whereas other instructions only take one, so if you use a 'nop' in a program it
takes 1uS to execute, and carries on from the next line - however, if you use 'goto $+1' it
still carries on from the next line, but now takes 2uS. You'll notice more use of the 'goto
$' construction in later tutorials, if you are checking an input pin and waiting for it to
change state you can use 'goto $-1' to jump back to the previous line, this saves
allocating a label to the line that tests the condition.

This is a table of the LCD subroutines provided in these programs, you can easily
add more if you wish - for instance to set a line cursor rather than a block one, if you
find you are using a particular feature a lot you may as well make a subroutine for it.
LCD Subroutines
LCD_Init

Initialise LCD Module

LCD_Cmd

Sent a command to the LCD

LCD_CharD

Add 0x30 to a byte and send to the LCD


(to display numbers as ASCII)

LCD_Char

Send the character in W to the LCD

LCD_Line1

Go to start of line 1

LCD_Line2

Go to start of line 2

LCD_Line1W Go to line 1 column W


LCD_Line2W Go to line 2 column W
LCD_CurOn Turn block cursor on
LCD_CurOff Turn block cursor off
LCD_Clr

Clear the display

LCD_HEX

Display the value in W as Hexadecimal

Tutorial 3.2 - requires Main Board and LCD Board.


This program displays a text message on the top line and a running 16 bit counter on
the bottom line, with the values displayed in both decimal and hexadecimal , it consists
mostly of the previous subroutines for using the LCD module, plus an extra one for
converting from 16 bit hexadecimal to decimal.
;LCD 16 bit counter
;Nigel Goodwin 2002
using
chip

LIST

p=16F628

;tell assembler what chip we are

include "P16F628.inc"

ERRORLEVEL
0,
messages
__config 0x3D18
(oscillator type etc.)

registers

cblock 0x20
count
count1
counta
countb
tmp1
tmp2

;include the defaults for the


-302

;suppress bank selection


;sets the configuration settings

;start of general purpose


;used in looping routines
;used in delay routine
;used in delay routine
;used in delay routine
;temporary storage

templcd
mode

;temp store for 4 bit

templcd2

NumL
decimal convert routine
NumH

;Binary inputs for

TenK
convert routine

endc
LCD_PORT
LCD_TRIS
LCD_RS
LCD_RW
LCD_E

;Decimal outputs from

Thou
Hund
Tens
Ones

Equ
Equ
Equ
Equ
Equ

PORTA
TRISA
0x04
0x06
0x07

org

0x0000

;LCD handshake lines

movlw
0x07
movwf
CMCON
(make it like a 16F84)

;turn comparators off

Initialise

clrf
clrf
clrf
clrf
clrf

count
PORTA
PORTB
NumL
NumH

SetPorts

bsf
movlw
movwf
bcf

STATUS,
0x00
LCD_TRIS
STATUS,

call

LCD_Init

;setup LCD

clrf

count

;set counter register to

movf
call

count, w
Text

;put counter value in W


;get a character from the

xorlw
btfsc
goto
call
incf
goto

0x00
STATUS, Z
NextMessage
LCD_Char
count, f
Message

;is it a zero?

call

LCD_Line2

;move to 2nd row, first

call

Convert

;convert to decimal

zero
Message
text table

NextMessage
column

RP0

;select bank 1
;make all pins outputs

RP0

;select bank 0

movf
characters

call
convert to ASCII
movf
call
movf
call
movf
call
movf
call
movlw
call
movf
hexadecimal
call
movf
call
incfsz
goto
incf
Next
call
digits change
goto

TenK,

;display decimal

LCD_CharD

;using LCD_CharD to

Thou,
w
LCD_CharD
Hund,
w
LCD_CharD
Tens,
w
LCD_CharD
Ones,
w
LCD_CharD
' '
LCD_Char
NumH,
w

;display a 'space'
;and counter in

LCD_HEX
NumL,
w
LCD_HEX
NumL,
f
Next
NumH,
f
Delay255

;wait so you can see the

NextMessage

;Subroutines and text tables


;LCD routines
;Initialise LCD
LCD_Init
call

mode

cursor command

Delay100

;wait for LCD to settle

movlw
call

0x20
LCD_Cmd

;Set 4 bit mode

movlw
call

0x28
LCD_Cmd

;Set display shift

movlw

0x06

;Set display character

call

LCD_Cmd

movlw

0x0c

;Set display on/off and

call

LCD_Cmd

;Set cursor off

call

LCD_Clr

;clear display

retlw

0x00

; command set routine


LCD_Cmd
movwf
swapf
andlw
movwf
bcf
call
movf

templcd
templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
templcd,

;send upper nibble


;clear upper 4 bits of W
;RS line to 0
;Pulse the E line high
;send lower nibble

andlw
movwf
bcf
call
call
retlw

0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
Delay5
0x00

;clear upper 4 bits of W

addlw

0x30

;add 0x30 to convert to

movwf
swapf
andlw
movwf
bsf
call

templcd
templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e

movf
andlw
movwf
bsf
call
call
retlw

templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
Delay5
0x00

;send lower nibble


;clear upper 4 bits of W

LCD_Line1
column

movlw

0x80

;move to 1st row, first

call
retlw

LCD_Cmd
0x00

LCD_Line2
column

movlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_Line1W
W

addlw

0x80

call
retlw

LCD_Cmd
0x00

LCD_Line2W
W

addlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_CharD
ASCII
LCD_Char

LCD_CurOn
movlw
cursor command
call
retlw

0x0d

LCD_CurOff
movlw
cursor command
call
retlw

0x0c

LCD_Clr

movlw
call
retlw

0x01
LCD_Cmd
0x00

LCD_HEX

movwf
swapf
andlw

tmp1
tmp1,
0x0f

;RS line to 0
;Pulse the E line high

;send upper nibble


;clear upper 4 bits of W
;RS line to 1
;Pulse the E line high

;RS line to 1
;Pulse the E line high

;move to 2nd row, first

;move to 1st row, column

;move to 2nd row, column

;Set display on/off and

LCD_Cmd
0x00
;Set display on/off and

LCD_Cmd
0x00
;Clear display

Delay255
Delay100
Delay50
Delay20
Delay5
d0
d1

Delay_0

call
call
movf
andlw
call
call
retlw

HEX_Table
LCD_Char
tmp1, w
0x0f
HEX_Table
LCD_Char
0x00

movlw
goto
movlw
goto
movlw
goto
movlw
goto
movlw
movwf
movlw
movwf
movlw
movwf

0xff
d0
d'100'
d0
d'50'
d0
d'20'
d0
0x05
count1
0xC7
counta
0x01
countb

decfsz
goto
decfsz
goto

counta, f
$+2
countb, f
Delay_0

;delay 255 mS
;delay 100mS
;delay 50mS
;delay 20mS
;delay 5.000 ms (4 MHz clock)
;delay 1mS

decfsz count1 ,f
goto
d1
retlw
0x00
Pulse_e

bsf
nop
bcf
retlw

LCD_PORT, LCD_E
LCD_PORT, LCD_E
0x00

;end of LCD routines


HEX_Table

ADDWF
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW

PCL
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x41
0x42
0x43
0x44
0x45
0x46

Text

addwf
retlw
retlw

PCL, f
'1'
'6'

, f

retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw

' '
'B'
'i'
't'
' '
'C'
'o'
'u'
'n'
't'
'e'
'r'
'.'
0x00

;This routine downloaded from http://www.piclist.com


Convert:
; Takes number in NumH:NumL
; Returns decimal in
; TenK:Thou:Hund:Tens:Ones
swapf
NumH, w
iorlw
B'11110000'
movwf
Thou
addwf
Thou,f
addlw
0XE2
movwf
Hund
addlw
0X32
movwf
Ones
movf
andlw
addwf
addwf
addwf
addlw
movwf
addwf
addwf

NumH,w
0X0F
Hund,f
Hund,f
Ones,f
0XE9
Tens
Tens,f
Tens,f

swapf
andlw
addwf
addwf

NumL,w
0X0F
Tens,f
Ones,f

rlf
rlf
comf
rlf

Tens,f
Ones,f
Ones,f
Ones,f

movf
andlw
addwf
rlf

NumL,w
0X0F
Ones,f
Thou,f

movlw
movwf

0X07
TenK
;
;
;
;
;

At this point, the original number is


equal to
TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
if those entities are regarded as two's
complement binary. To be precise, all of

; them are negative except TenK. Now the number


; needs to be normalized, but this can all be
; done with simple byte arithmetic.
Lb1:

Lb2:

Lb3:

Lb4:

movlw

0X0A

addwf
decf
btfss
goto

Ones,f
Tens,f
3,0
Lb1

addwf
decf
btfss
goto

Tens,f
Hund,f
3,0
Lb2

addwf
decf
btfss
goto

Hund,f
Thou,f
3,0
Lb3

addwf
decf
btfss
goto

Thou,f
TenK,f
3,0
Lb4

retlw

0x00

; Ten

end

Tutorial 3.3 - requires Main Board and LCD Board.


This program displays a text message on the top line and a running 16 bit counter on
the bottom line, just as the last example, however, instead of using the Delay calls this
version waits until the LCD Busy flag is clear. The LCD module takes time to carry out
commands, these times vary, and the previous tutorials used a delay more than long
enough to 'make sure' - however, the modules have the capability of signalling when
they are ready, this version uses that facility and avoids any unnecessary delays. I've
also used the LCD_Line2W routine to position the numbers further to the right and
demonstrate the use of the routine, another slight change is that the tables have been
moved to the beginning of program memory, this was done because it's important that
tables don't cross a 256 byte boundary, so putting them at the start avoids this.
;LCD 16 bit counter - using LCD Busy line
;Nigel Goodwin 2002
LIST
using
chip

p=16F628

;tell assembler what chip we are

include "P16F628.inc"

ERRORLEVEL
0,
messages
__config 0x3D18
(oscillator type etc.)

;include the defaults for the


-302

;suppress bank selection


;sets the configuration settings

cblock 0x20
registers

;start of general purpose

count
count1
counta
countb
tmp1
tmp2
templcd

mode

;used in looping routines


;used in delay routine
;used in delay routine
;used in delay routine
;temporary storage
;temp store for 4 bit

templcd2

NumL
decimal convert routine
NumH

;Binary inputs for

TenK
convert routine

endc
LCD_PORT
LCD_TRIS
LCD_RS
LCD_RW
LCD_E

;Decimal outputs from

Thou
Hund
Tens
Ones

Equ
Equ
Equ
Equ
Equ

PORTA
TRISA
0x04
0x06
0x07

org
goto

0x0000
Start

HEX_Table

ADDWF
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW

PCL
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x41
0x42
0x43
0x44
0x45
0x46

Text

addwf
retlw
retlw
retlw
retlw
retlw
retlw

PCL, f
'1'
'6'
' '
'B'
'i'
't'

;LCD handshake lines

, f

retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw
retlw

' '
'C'
'o'
'u'
'n'
't'
'e'
'r'
'.'
0x00

Start

movlw
0x07
movwf
CMCON
(make it like a 16F84)

;turn comparators off

Initialise

clrf
clrf
clrf
clrf
clrf

count
PORTA
PORTB
NumL
NumH

SetPorts

bsf
movlw
movwf
movwf
bcf

STATUS,
0x00
LCD_TRIS
TRISB
STATUS,

call

LCD_Init

;setup LCD

clrf

count

;set counter register to

movf
call

count, w
Text

;put counter value in W


;get a character from the

xorlw
btfsc
goto
call
incf
goto

0x00
STATUS, Z
NextMessage
LCD_Char
count, f
Message

;is it a zero?

movlw
call

d'2'
LCD_Line2W

;move to 2nd row, third

call
movf

Convert
TenK,
w

;convert to decimal
;display decimal

call
convert to ASCII
movf
call
movf
call
movf
call
movf
call

LCD_CharD

;using LCD_CharD to

zero
Message
text table

NextMessage
column

characters

Thou,
w
LCD_CharD
Hund,
w
LCD_CharD
Tens,
w
LCD_CharD
Ones,
w
LCD_CharD

RP0

;select bank 1
;make all pins outputs

RP0

;select bank 0

hexadecimal

Next
digits change

movlw
call
movf

' '
LCD_Char
NumH,
w

call
movf
call
incfsz
goto
incf
call

LCD_HEX
NumL,
w
LCD_HEX
NumL,
f
Next
NumH,
f
Delay255

goto

NextMessage

;display a 'space'
;and counter in

;wait so you can see the

;Subroutines and text tables


;LCD routines
;Initialise LCD
LCD_Init
call

mode

cursor command

LCD_Busy

;wait for LCD to settle

movlw
call

0x20
LCD_Cmd

;Set 4 bit mode

movlw
call

0x28
LCD_Cmd

;Set display shift

movlw

0x06

;Set display character

call

LCD_Cmd

movlw

0x0c

;Set display on/off and

call

LCD_Cmd

;Set cursor off

call

LCD_Clr

;clear display

retlw

0x00

; command set routine


LCD_Cmd
movwf
swapf
andlw
movwf
bcf
call

LCD_CharD
ASCII
LCD_Char

templcd
templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e

;send upper nibble


;clear upper 4 bits of W
;RS line to 0
;Pulse the E line high

movf
andlw
movwf
bcf
call
call
retlw

templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
LCD_Busy
0x00

;send lower nibble


;clear upper 4 bits of W

addlw

0x30

;add 0x30 to convert to

movwf
swapf
andlw

templcd
templcd,
0x0f

;RS line to 0
;Pulse the E line high

;send upper nibble


;clear upper 4 bits of W

movwf
bsf
call

LCD_PORT
LCD_PORT, LCD_RS
Pulse_e

movf
andlw
movwf
bsf
call
call
retlw

templcd,
w
0x0f
LCD_PORT
LCD_PORT, LCD_RS
Pulse_e
LCD_Busy
0x00

;send lower nibble


;clear upper 4 bits of W

LCD_Line1
column

movlw

0x80

;move to 1st row, first

call
retlw

LCD_Cmd
0x00

LCD_Line2
column

movlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_Line1W
W

addlw

0x80

call
retlw

LCD_Cmd
0x00

LCD_Line2W
W

addlw

0xc0

call
retlw

LCD_Cmd
0x00

LCD_CurOn
movlw
cursor command
call
retlw

0x0d

LCD_CurOff
movlw
cursor command
call
retlw

0x0c

LCD_Clr

movlw
call
retlw

0x01
LCD_Cmd
0x00

LCD_HEX

movwf
swapf
andlw
call
call
movf
andlw
call
call
retlw

tmp1
tmp1,
w
0x0f
HEX_Table
LCD_Char
tmp1, w
0x0f
HEX_Table
LCD_Char
0x00

Delay255

movlw
goto
movlw
goto

0xff
d0
d'100'
d0

Delay100

;RS line to 1
;Pulse the E line high

;RS line to 1
;Pulse the E line high

;move to 2nd row, first

;move to 1st row, column

;move to 2nd row, column

;Set display on/off and

LCD_Cmd
0x00
;Set display on/off and

LCD_Cmd
0x00
;Clear display

;delay 255 mS
;delay 100mS

Delay50
Delay20
Delay5
clock)
d0
d1

Delay_0

movlw
goto
movlw
goto
movlw

d'50'
d0
d'20'
d0
0x05

movwf
movlw
movwf
movlw
movwf

count1
0xC7
counta
0x01
countb

decfsz
goto
decfsz
goto

counta, f
$+2
countb, f
Delay_0

;delay 50mS
;delay 20mS
;delay 5.000 ms (4 MHz
;delay 1mS

decfsz count1 ,f
goto
d1
retlw
0x00
Pulse_e

bsf
nop
bcf
retlw

LCD_PORT, LCD_E

bsf
movlw
movwf
bcf
bcf
bsf
bsf
swapf

STATUS, RP0
0x0f
LCD_TRIS
STATUS, RP0
LCD_PORT, LCD_RS
LCD_PORT, LCD_RW
LCD_PORT, LCD_E
LCD_PORT, w

bcf
movwf
bsf

LCD_PORT, LCD_E
templcd2
LCD_PORT, LCD_E

;dummy read of lower

bcf
btfsc

LCD_PORT, LCD_E
templcd2, 7

;check busy flag, high =

goto
bcf
bsf
movlw
movwf
bcf
return

LCD_Busy
LCD_PORT, LCD_RW
STATUS, RP0
0x00
LCD_TRIS
STATUS, RP0

LCD_PORT, LCD_E
0x00

LCD_Busy

flag)

nibble
busy

;set bank 1
;set Port for input
;set bank 0
;set LCD for command mode
;setup to read busy flag
;read upper nibble (busy

;if busy check again


;set bank 1
;set Port for output
;set bank 0

;end of LCD routines

;This routine downloaded from http://www.piclist.com


Convert:
; Takes number in NumH:NumL
; Returns decimal in
; TenK:Thou:Hund:Tens:Ones
swapf
NumH, w
iorlw
B'11110000'

movwf
addwf
addlw
movwf
addlw
movwf

Thou
Thou,f
0XE2
Hund
0X32
Ones

movf
andlw
addwf
addwf
addwf
addlw
movwf
addwf
addwf

NumH,w
0X0F
Hund,f
Hund,f
Ones,f
0XE9
Tens
Tens,f
Tens,f

swapf
andlw
addwf
addwf

NumL,w
0X0F
Tens,f
Ones,f

rlf
rlf
comf
rlf

Tens,f
Ones,f
Ones,f
Ones,f

movf
andlw
addwf
rlf

NumL,w
0X0F
Ones,f
Thou,f

movlw
movwf

0X07
TenK
;
;
;
;
;
;
;
;

Lb1:

Lb2:

Lb3:

Lb4:

movlw

0X0A

addwf
decf
btfss
goto

Ones,f
Tens,f
3,0
Lb1

addwf
decf
btfss
goto

Tens,f
Hund,f
3,0
Lb2

addwf
decf
btfss
goto

Hund,f
Thou,f
3,0
Lb3

At this point, the original number is


equal to
TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
if those entities are regarded as two's
complement binary. To be precise, all of
them are negative except TenK. Now the number
needs to be normalized, but this can all be
done with simple byte arithmetic.
; Ten

addwf
decf
btfss
goto

Thou,f
TenK,f
3,0
Lb4

retlw

0x00
end

You might also like