|
Interfacing
to LCD Display
Most projects you create with the 8051 CPU
require some form of display. The most common way to
accomplish this is with the LCD (Liquid Crystal Display). LCDs
have become a cheap and easy way to get text display for an embedded
system Common displays are set up as 16 to 20 characters by 1 to 4
lines.
UNDERSTANDING LCD
Pinout
• 8 data pins D7:D0
Bi-directional data/command pins. Alphanumeric characters are
sent in ASCII format.
•
RS: Register Select
RS = 0 -> Command Register is selected RS = 1 -> Data
Register is selected
•
R/W: Read or Write
0
-> Write, 1 -> Read
•
E: Enable (Latch data)
Used to latch the data present on the data pins. A high-to-low
edge is needed to latch the data.
•
VEE : contrast control
NOTE: When writing to the display, data is transferred only on the
high to low transition of this signal. However, when reading from the
display, data will become available shortly after the low to high
transition and remain available until the signal falls low
again.
Display Data RAM (DDRAM)
Display data RAM (DDRAM) is where you send
the characters (ASCII code) you want to see on the LCD screen. It stores
display data represented in 8-bit character codes. Its capacity is 80
characters (bytes). Below you see DD RAM address layout of a 2*16
LCD.

In the above memory map, the area shaded in black is the visible
display (For 16x2 display) .
For first line addresses for first 15 characters is from 00h to
0Fh. But for second line address of first character is 40h and so on up to
4Fh for the 16th character.
So if you want to display the text at
specific positions of LCD , we require to manipulate address and then to
set cursor position accordingly .
Character Generator RAM (CGRAM)-User defined
character RAM
In the character generator RAM, we can define
our own character patterns by program. CG RAM is 64 bytes ,allowing
for eight 5*8 pixel, character patterns to be defined. However how to
define this and use it is out of scope of this tutorial. So I will not
talk any more about CGRAM
Registers
The HD44780 has two 8-bit registers, an
instruction register (IR) and a data register (DR). The IR stores
instruction codes. The DR temporarily stores data to be written into DDRAM
or CGRAM and temporarily stores data to be read from DDRAM or CGRAM. Data
written into the DR is automatically written into DDRAM or CGRAM by an
internal operation. . These two registers can be selected by the register
selector (RS) signal. See the table below:
|
|
|
Register
Selection |
|
RS |
R/W |
Operation |
|
0 |
0 |
IR write
as an internal operation (display clear, etc.) |
|
0 |
1 |
Read
busy flag (DB7) and address counter (DB0 to DB6) |
|
1 |
0 |
DR write
as an internal operation (DR to DDRAM or CGRAM) |
|
1 |
1 |
DR read
as an internal operation (DDRAM or CGRAM to
DR) |
Busy Flag (BF)
When the busy flag is 1, the LCD is
in the internal operation mode, and the next instruction will not be
accepted. When RS = 0 and R/W = 1 (see the table above), the busy flag is
output to DB7 (MSB of LCD data bus). The next instruction must be written
after ensuring that the busy flag is 0.
LCD Commands
The LCD’s internal controller accept several commands and
modify the display accordingly. These commands would be things like: –
Clear screen – Return home – Shift display
right/left
|
Instruction |
Decimal |
HEX |
|
Function set (8-bit interface, 2 lines, 5*7 Pixels) |
56 |
38 |
|
Function set (8-bit interface, 1 line, 5*7 Pixels) |
48 |
30 |
|
Function set (4-bit interface, 2 lines, 5*7 Pixels) |
40 |
28 |
|
Function set (4-bit interface, 1 line, 5*7 Pixels) |
32 |
20 |
|
Entry mode set |
See
Below |
See
Below |
|
Scroll display one character right (all lines) |
28
|
1E |
|
Scroll display one character left (all lines) |
24
|
18 |
|
Home (move cursor to top/left character position) |
2
|
2 |
|
Move
cursor one character left |
16
|
10 |
|
Move
cursor one character right |
20
|
14 |
|
Turn
on visible underline cursor |
14
|
0E |
|
Turn
on visible blinking-block cursor |
15 |
0F |
|
Make
cursor invisible |
12
|
0C |
|
Blank the display (without clearing) |
8
|
08 |
|
Restore the display (with cursor hidden) |
12
|
0C |
|
Clear Screen |
1
|
01 |
|
Set cursor position (DDRAM address) |
128 +
addr |
80+
addr |
|
Set pointer in character-generator RAM (CG RAM address)
|
64 + addr
|
40+
addr |
Entry mode set
This command sets cursor move
direction and display shift ON/OFF. There are 4 possible function set
commands;04, 05, 06, and 07. This command changes the direction the cursor
moves by setting the address counter to increment or decrement. This
command is very important. If you do not understand it you may not see
anything or what you actually wanted to see on LCD screen. I have created
4 animated gifs to demonstrate what the function set command is all
about.
Set cursor position (DDRAM
address)
As said earlier if we want to display the text at specific
positions of LCD , we require to manipulate address and then to set cursor
position accordingly.
I
want to display "MAHESH" in message "Hi MAHESH" at the right corner of
first line then I should start from 10th character.
So referring to table 80h+0Ah= 8Ah.
INTERFACING LCD TO 8051

The 44780 standard requires 3 control lines
as well as either 4 or 8 I/O lines for the data bus. The user may select
whether the LCD is to operate with a 4-bit data bus or an 8-bit data bus.
If a 4-bit data bus is used, the LCD will require a total of 7 data
lines.
If an 8-bit data bus is used, the LCD will require a total of 11
data lines.
The three control lines are EN,
RS, and RW.
Note that the EN line must be raised/lowered
before/after each instruction sent to the LCD regardless of whether that
instruction is read or write, text or instruction. In short, you must
always manipulate EN when communicating with the LCD. EN is the LCD's way
of knowing that you are talking to it. If you don't raise/lower EN, the
LCD doesn't know you're talking to it on the other lines.
Checking the Busy
Flag
You can use subroutine for checking busy flag or
just a big (and safe) delay.
-
Set R/W Pin of the LCD HIGH(read from the LCD)
-
Select the instruction register by setting RS pin
LOW
-
Enable the LCD by Setting the enable pin HIGH
-
The most significant bit of the LCD data bus is the
state of the busy flag(1=Busy,0=ready to accept instructions/data). The
other bits hold the current value of the address counter.
If the LCD never come out from "busy"
status because of some problems ,The program will "hang," waiting
for DB7 to go low. So in a real applications it would be wise to put some
kind of time limit on the delay--for example, a maximum of 100 attempts to
wait for the busy signal to go low. This would guarantee that even if the
LCD hardware fails, the program would not lock up.
CODE EXAMPLE
It is easy (and clean tech. ) to make different subroutines and
then call them as we need.
| Busy flag
checking |
|
Data write
Routine |
|
Command write Routine |
|
ready:
setb P1.7 ;D7 as input clr P3.6 ;RS=0 cmd setb P3.5
;RW=1 for read
again:
setb P3.7 ;H->L pulse on E clr P3.7 jb P1.7,
again ret |
|
data:
mov P1, A ;move acc. data to port setb P3.6
;RS=1 data clr P3.5 ;RW=0 for write setb P3.7 ;H->L pulse
on E clr P3.7 lcall ready
ret |
|
|
command: mov P1, A ;move acc. data to port clr P3.6 ;RS=0 for cmd clr P3.5 ;RW=0 for
write setb P3.7 ;H->L pulse on E clr P3.7
lcall ready
ret |
|
Initialization |
|
Display
clear |
|
Displaying
"HI" |
|
initialization:
mov A,
#38H ; Initialize, 2-lines, 5X7 matrix. lcall
Command mov A, #0EH ; LCD on, cursor on lcall
Command mov A, #01H ; Clear LCD Screen lcall
Command mov A, #06H ; Shift cursor right lcall Command |
|
clear: setb p3.7 ;enable EN clr 3.6 ;RS=0 for
cmd. mov DATA,#01h clr p3.7 ;disable EN lcall
ready RET
Note- As we need to clear the LCD frequently and
not the whole initialisation , it is better to use this routine
separately. |
|
|
lcall
initialization
lcall
clear mov A,#'H'
acall
data
mov A,#'I' lcall
data |
Let's now try code for displaying text at specific
positions.
I want to display "MAHESH" in message "Hi MAHESH" at
the right corner of first line then I should start from 10th
character.

So referring to table 80h+0Ah= 8Ah.
So below is code and I don's think that you
will need explanation comments.
|
ASSEMBLY
LANGUAGE |
|
|
|
lcall Initialization lcall clear mov
a,#'H' lcall data mov a,#'I' lcall data
mov a,#8ah lcall
command
mov a,#'M' lcall data mov
a,#'A' lcall data mov a,#'H' lcall data mov
a,#'E' lcall data mov a,#'S' lcall data mov
a,#'H' lcall data |
|
|