A 16x2 LCD     HD44780 Controlled LCD

Introduction

LCD' s add a  more professional look to most any project as apposed to seven segment or alpha-numeric LED's.  Most character LCD's are controlled via an industry standard HD44780-style controller.  This is great because almost any character LCD you purchase will operate in the exact same manner.  Once you have learned a few subtle nuances of the Hitachi interface, you will be able to easily add attractive output or debugging to any project you try to tackle.

Pin Out

The pin out on most LCD's will be 14 to 16 pins in a single row with the standard 100 mil spacing.  The 16 pin version has two extra pins to accommodate a back-light.  However, sometimes the pins are present but not connected to anything.  I guess this allows the manufacturer to have just one board layout for both models.  It's always best to look up a datasheet for your part, but the pin out really is very standardized.

Pin Function
1 Ground (Vss), 0V
2 Power (Vdd), +5V
3 Contrast Voltage (usually less than 1V)
4 "R/S" Register Select ( 1 for Data Write, 0 for Command Write)
5 "R/W" Read/Write (1 for Read, 0 for Write)
6 "EN" Enable line (Pulsing high latches a command or data _||_ )
7-14 Data Pins (D0-D7) D0 is LSB, in 4-bit mode only D4-D7 are used
15-16 (Optional) Back-light Anode and Cathode, NC, or Not There at All

Schematics

There are two basic ways to interface the device: 8-bit mode and 4-bit mode.  Most often, the "R/W" line is just tied to ground, and the LCD is only written to and not read.  The read function is usually used to poll the "Busy Flag" which appears on D7 while the device is incapable of accepting a command (it's busy..get it).  However, this function may be ignored by simply waiting the maximum amount of time for each command to complete (most are completed in less than 200us).  So, I will only discuss the scenario in which "R/W" is grounded.

8-Bit Interface

Schematic 8 bit Interface

4-Bit Interface

Schematic 4-bit interface
The 180-ohm resistor going into the Anode pin is to bias the LED back-light on the model I was using when I made this schematic.  Your model may not have a back-light, it may need a different value resistor, or you may choose to ignore the back-light all together and save some parts; it's up to you. Also, it isn't shown here, but you should put a 0.1uF or 0.01uF ceramic capacitor near the LCD between Vss and Vdd to act as a filter for high frequency noise.

Writing Data and Commands

In order to write a command or data do the following for both modes:

8-Bit Write Sequence
Make Sure "EN" is 0 or low
Set "R/S" to 0 for a command, or 1 for data/characters
Put the data/command on D7-0
Set "EN" (EN= 1 or High)
Wait At Least 450 ns!!!
Clear "EN" (EN= 0 or Low)
Wait 5ms for command writes, and 200us for data writes.


4-Bit Write Sequence
Make Sure "EN" is 0 or low
Set "R/S" to 0 for a command, or 1 for data/characters
Put the HIGH BYTE of the data/command on D7-4
Set "EN" (EN= 1 or High)
Wait At Least 450 ns!!!
Clear "EN" (EN= 0 or Low)
Wait 5ms for command writes, and 200us for data writes.
Put the LOW BYTE of the data/command on D7-4
Wait At Least 450 ns!!!
Clear "EN" (EN= 0 or Low)
Wait 5ms for command writes, and 200us for data writes.

Command Set

R/S R/W D7 D6 D5 D4 D3 D2 D1 D0 Instruction/Description
0 0 0 0 0 0 0 0 0 1 Clear Display and Home the Cursor
0 0 0 0 0 0 0 0 1 * Return Cursor and LCD to Home Position
0 0 0 0 0 0 0 1 ID S Set Cursor Move Direction
0 0 0 0 0 0 1 D C B Enable Display/Cursor
0 0 0 0 0 1 SC RL * * Move Cursor/Shift Display
0 0 0 0 1 DL N F * * Set Interface Length
0 0 0 1 A A A A A A Move Cursor into CGRAM
0 0 1 A A A A A A A Move Cursor to Display
0 1 BF * * * * * * * Poll the "Busy Flag"
1 0 D D D D D D D D Write a Character to the Display at the Current Cursor Position
1 1 D D D D D D D D Read the Character on the Display at the Current Cursor Position

The bit descriptions for the different commands are:

"*" - Not Used/Ignored. This bit can be either "1" or "0"

Set Cursor Move Direction:
ID - Increment the Cursor After Each Byte Written to Display if Set
S - Shift Display when Byte Written to Display

Enable Display/Cursor
D - Turn Display On(1)/Off(0)
C - Turn Cursor On(1)/Off(0)
B - Cursor Blink On(1)/Off(0)

Move Cursor/Shift Display
SC - Display Shift On(1)/Off(0)
RL - Direction of Shift Right(1)/Left(0)

Set Interface Length
DL - Set Data Interface Length 8(1)/4(0)
N - Number of Display Lines 1(0)/2(1)
F - Character Font 5x10(1)/5x7(0)

Poll the "Busy Flag"
BF - This bit is set while the LCD is processing

Move Cursor to CGRAM/Display
A - Address

Read/Write ASCII to the Display
D - Data

Initialization

There are, of course, two different ways to initialize the LCD: 4-bit mode, and 8-bit mode. It is interesting to note that a four-line LCD initializes just like a two-line LCD.  In fact, the setup is usually just two HD44780-style controllers, but to the user it is transparent.  The only weird part is that the lines are addressed such that both of the line 1's precede both line 2's of each controller, which make the addresses non-consecutive.  So, if you just set the display to shift the cursor right after each character write, the display will wrap, eventually, from the 1st line to the 3rd line to the 2nd line and, finally, to the 4th line.

I will show a general form of how to initialize the display as well as an example.  The example will initialize a 2-line (or 4-line, they initialize the same) to shift the cursor right after each character write, display no cursor, and of course turn on the LCD for viewing.

Unless explicitly noted "Write" means follow the instructions outlined in the section "Writing Data and Commands."  Else an enable pulse is to be provided followed by waiting the stated amount of time.

Remember: For commands RS = 0, for data RS = 1

8-Bit Initialization


General Initialization Example Initialization
1 Wait 20ms for LCD to power up
2 Write D7-0 = 30 hex, with RS = 0
3 Wait 5ms
4 Write D7-0 = 30 hex, with RS = 0, again
5 Wait 200us
6 Write D7-0 = 30 hex, with RS = 0, one more time
7 Wait 200us
8 Write Command "Set Interface" Write 38 hex (8-Bits, 2-lines)
9 Write Command "Enable Display/Cursor" Write 08 hex (don't shift display, hide cursor)
10 Write Command "Clear and Home" Write 01 hex (clear and home display)
11 Write Command "Set Cursor Move Direction" Write 06 hex (move cursor right)
12 -- Write 0C hex (turn on display)
Display is ready to accept data.

4-Bit Initialization

Remember:  Data/Command writes of the size one byte are done high-nibble, delay, low-nibble, delay. (1 nibble = 4 bits)

General Initialization Example Initialization
1 Wait 20ms for LCD to power up
2 Write D7-4 = 3 hex, with RS = 0
3 Wait 5ms
4 Write D7-4 = 3 hex, with RS = 0, again
5 Wait 200us
6 Write D7-4 = 3 hex, with RS = 0, one more time
7 Wait 200us
8 Write D7-4 = 2 hex, to enable four-bit mode
9 Wait 5ms
10 Write Command "Set Interface" Write 28 hex (4-Bits, 2-lines)
11 Write Command "Enable Display/Cursor" Write 08 hex (don't shift display, hide cursor)
12 Write Command "Clear and Home" Write 01 hex (clear and home display)
13 Write Command "Set Cursor Move Direction" Write 06 hex (move cursor right)
14 -- Write 0C hex (turn on display)
Display is ready to accept data.

Address Locations

2-Line Display

LCD
Line 1 00 hex, 01 hex, 02 hex,...........          
Line 2 40 hex, 41 hex, 42 hex,...........

4-Line Display

LCD
Line 1 00 hex, 01 hex, 02 hex,...........          
Line 2 40 hex, 41 hex, 42 hex,...........
Line3 20 hex, 21 hex, 22 hex,...........
Line 4 60 hex, 61 hex, 62 hex,...........

Some Useful Commands

Command (in hex) Effect
0C Turns ON JUST the LCD, no cursor
08 Turns OFF the LCD display
0E Turns on the LCD display and Sets a SOLID CURSOR
0F Turns on the LCD display and Sets a BLINKING CURSOR
80 Moves cursor to first address on the left of LINE 1
C0 Moves cursor to first address on the left of LINE 2
94 Moves cursor to first address on the left of LINE 3
D4 Moves cursor to first address on the left of LINE 4

Also, note that adding an offset to the line commands will move the cursor to different places within the line provided you don't exceed the addresses in the line.  So, for example, 80h + 2h will move your cursor to the third position of the first line.  Most compilers will let you define a string and allow a statement like this:

; LCD Constants
LINE1                     equ                  080h         ; or #define   LINE1    0x80
;
;   8051 code
mov    lcdRegister, LINE1+2                            ; set the register to be passed to the...
                                                                        ; ...subroutine to 3rd spot of 1st line
call     writeCommandSubroutine                       ; write the command
;
or
;  PIC code
movlw  LINE1+2
call       writeCommandSubroutine                     ; does the same thing for a PIC




Back to Top