Back to Top



LCD stands for Liquid Crystal Displays

Image not found...
(Fig1) A Common 2x16 LCD.
Lcd's are widely spread out these days. There are really cheap, and produced with a variety of shapes and sizes.
You can find them with 8, 16, 20, 24, 32, 40 characters and in combination of 1, 2, or 4 line versions.
With the most common of them the 2x16 (Fig1) or 4x20.
Most of them use the HITACHI'S HD44780 controller or equivalent. ( This chip was launched by HITACHI in early 80's. )
One cool feature that these modules have, ( among their controlling simplicity ) is that you can project symbols created by
you from scratch!!! ( For example: a bell or an hourglass .... )
These modules have default letters and numbers in their built-in rom, but we will analyze furthermore below on this tutorial,
of how would be possible to create our custom symbols ...
Closing this brief introduction it is worth saying that there are modules called "Supertwist" which are offering better contrast
and viewing angle, in comparison the older ones which are called "Twisted Nematic".
But picking decisions should be made according to our needs and uses ...

Pinout Description

It's time to have a look at the pinout of the LCD..... Most of the lcd's have a common 16-pinout connector. But some of them (very rare these days) have a 14-pinout connector, and that's because they don't have backlight illumanation.

In summary.... there are:

8 Data lines (D0 to D7)
3 Control lines (RS, RW, E)
3 Power lines (including contrast) and
2 Led's backlight illumination.

These pinout connections are placed either in 2 rows of 8 pins (Fig3) or a single row of 16 pins. (Fig2) Which is also and the most common.
Right now we will see each pin individually and analyze each role of it.

Image not found...
(Fig2) The 16-Pinout in a single row.
Image not found...
(Fig3) The 16-Pinout in 2 rows of 8 pins.

Pin #
Is the ground and usually by default the first pin of the lcd.
Is the positive supply of the lcd.
Datasheet specifies that a 5vdc supply is the nominal voltage of the lcd, but 6v and 4.5v supplies are acceptable.
It has been noticed that for some display modules, 3v can make them work just fine.
Is the contrast of the lcd.
In this pin you can connect a fixed value resistor across the ground, or much and more preferable a trimmer of 5kΩ
in order to adjust the contrast accordinally the ambient temperature. Deviations to ambient temperature is the reason
for the lcd that needs to be adjusted.
Is the register select pin.
This pin is used to select whether data or command is being transferred to the lcd.
If this pin is high then data can be transferred FROM or TO the lcd at the current lcd cursor position.
If this pin is low a command can be transfered to lcd, or execution status of the last instruction is read back
(whether is or not completed) Rule of thumb { 0 = Command input 1 = Data input }
Is the read / write pin.
When this pin is low, you can write commands or character data to lcd.
When this pin is high, you can read character data and status information from lcd's registers.
For most applications there is no reason to read from lcd.
Reading data is used in applications which is required for data to be moved back and forth the lcd.(a scrolling message)
"Busy flag" can be polled to determine when the last instruction that has been sent, has been completed processing.
Is the enable pin.
This input pin initiates the actual data or command transfer, taken by the 8-bit (D0 to D7) data lines if the lcd was initialized
in 8-bit transfer mode, or in 4-bit (D4 to D7) data lines if the module has been initialized to 4-bit transfer mode.
Writing to the display data will be transferred only on the high to low transition, in contary reading from the display
data will be readable shortly after the low to high transition, and remain readable until the signal falls low again.
Are the eight data bus lines.
Data can be transfered to or from the display either as a single 8-bit byte or as two 4-bit nibbles.
If 4-bit mode is used only the upper 4 data lines (D4 to D7) are used, leaving the other 4 data lines (D0 to D3) floating.
When using 4-bit mode, it has a positive advantage that you can save pins from a microcontroller.
But if speed is required then 8-bit function is advisable.
Is the backlight illumination.
These two pins are the anode and the cathode of the led(s), that are placed behind the lcd panel for its illumination.
Usually pin15 is the anode of the led(s) (+), and pin16 is the cathode of the led(s) (-).

LCD Panel Organazation - Addressing

It is worth saying a little bit about the panel organazation that these modules have. (Since this is a tutorial for lcd's)
Below, there are some figures that illustrate the most commonly panel organazations, with a brief description of their variations...

40 Columns x 2 Rows :

Each controller (HD44780) can drive by itself 8 columns by 2 rows. So larger lcd modules, use an expansion driver module (HD44100) controller (or equivalent) to accomplish the task of previewing up to 40 columns .
Image not found...
(Fig4) This is the panel organazation of an lcd ( 40x2 )
This organazation will drive up to 40 columns by 2 rows (Click to enlarge)

16 Columns x 1 Row :

As we said before an HD44780 can drive by itself an 8 columns by 2 rows. So we take this as an advantage to create a configuration of 16 x 1, by placing the
second row to right side of the first row. Also with the particular configuration we eliminate the need of a segment expansion driver chip (HD44100).

Image not found...
(Fig5) This is the panel organazation of an lcd ( 16x1 ).
(Click to enlarge)

20 Columns x 4 Rows :

So far we have analyzed lcds with 1 and 2 rows... Now lets have a look of a 4 row organazation panel.
4 row panels are configured by placing the right half of charactrers (21-40) to the lower left (Fig6).
The first line is split (multiplexed) into the first and the third line of the lcd panel, and the second line is split (multiplexed) into the second and fourth line of the lcd panel.

Image not found...
(Fig6) This is the panel organazation of a 20x4 lcd.
(Click to enlarge)

11 Line Mode :

In this mode the lcd uses the rows from 1 to 10, so it can typify letters such as g, j, p, q and y , just like you write them down on a piece of paper.
The 11-nth row is reserved for the cursor line, and also rows from 12 to 16 are not used.
As a result in this mode we have characters with 10 lines of height instead of 8, but that creates a big disadvantage, which is the abolition of the second row.
So 2-rows display, is not available when using this mode.

Image not found...
(Fig7) 11-Line mode orientation.
(Click to enlarge)

Addressing :

Below is a table with addressing variations in different lcd modules. Orientation and placing is done as we have described to the paragraph above.
These are the most common lcd modules, and that's why i have made this table of them.

Image not found...
(Fig8) Position addressing in different modules.
(Click to enlarge)

Basic commands - Timings - Initialization

Image not found...
(Fig9) Black cubes printed on the lcd.
(Click to enlarge)
When you first power the lcd module, you may notice black cubes printed on lcd screen (Fig9).
Usually to the first line (if the lcd has a 2 rows display panel), or to the first and the third line
(if the lcd has a 4 row display panel).This is mentioned because in that state lcd must be initialized.
(usually it is not noticable since mcu initialize it before reaches that point.)

From the timing chart as we will see furthermore, we must provide to the lcd a delay of 15ms (least...i would recommend 50ms or more) before initialization procedure. That delay is crusial because VCC has to reach the nomimal voltage of 5V, so that the lcd would be able to accept commands. Sending commands before this period will result of initialization failure.
Before we move on initialization we must analyze few things... let's begin with lcd's command set.

Commands Set :

Image not found...
(Fig10) HD44800 Commands. (Click to enlarge)

All and all there are only 8 commands to mnemonize.Prettty easy!
As you can see from above, each command has configurable bits where you can set your lcd accordingly your needs.
(Further analysis below during initialization procedure explanation.)

Timings :

Next is timings. We must understand the timings that these modules have, in order to accept commands properly.

Image not found...
(Fig11) Command execution times
(Click to enlarge)
Image not found...
(Fig12) Timing Parameters
(Click to enlarge)

So what are all these diagrams and tables about?
Fig13 provides information for read and write cycles. In other words Fig13 showing us how quickly the lcd can respond, so that we can program our mcu accordingly. Fig12 are the timing parameters to Fig13. What really matters is that all these signals must be stable for a minimum or a maximum period of time.
For example lines RS and R/W must be stable for a minimum period of time before level logic on the 'E' line is raised to a logic 1.
This is named on the diagram as 'tAS' (time-address set up) and it is specified as 140ns minimum. It can be more but not less!!!.
Once the 'E' line is high it must not be brought low until 450ns has elapsed. This is named as 'tEH' (time - enable high).
In addition to that the data lines must be set to their appropriate logic levels and be allowed to stabilize for at least the 'tDS' (time - data setup) which is a period
of 200ns before bringing line 'E' low again. Keep in mind that data lines can be set up after line 'E' is taken high. (Or before...either condition is allowed)
When line 'E' has returned to a low logic level there are two hold times that you must take in account...
The 'tAH' (time - address hold) which reffers to RS and R/W lines, where must not be altered either 0 or 1 for at least 10ns and
the 'tDH' (time - data hold) which reffers to the data lines that must not be changed for at least 20ns.
Finally line 'E' must not be brought back high again until the period of 'tEL' (time - enable low) has reached 500ns.
So 'E' line has a 'reserved' time of 950ns (high-low) plus the rise and fall time 'tRF' which must not be longer than 25ns.
This is translated as no more than one million commands or one million characters per second should be sent to lcd.
Image not found...
(Fig13) HD44780 Timing Diagram
Click to enlarge

Initialization :

Now i believe is a good time to see how you can initialize an lcd by sending it commands, and making it work as you wish...
Having all that said, you may remember from before that these lcd's can be controlled either in 8-bit or in 4-bit bus mode.
The following chart shows the proper initialazation taken by hitachi's datasheet in both bus modes.

Image not found...
(Fig14) 8-bit, 4-bit initialization procedure.
(Click to enlarge)

I will analyze the 4-bit mode initialization since you can save more pins to your mcu. It is prettty much the same procedure in 8-bit bus mode,
but instead of sending nibbles to the lcd you send the whole byte.
So some may ask what is a nibble?
In computing nibble is an expression that refers to a half byte or to a quarter byte. One 8-bit byte consists of two nibbles.
The upper four bits (bit7 to bit4) also known as MSB (Most Significant Bits) and the lower four bits (bit3 to bit0) also known as LSB (Least Significant Bits).
The transmition priority for the nibbles in these lcd's is that in the first cycle you send the upper four following by the lower four on the following cycle.

After we power on the lcd, we must provide a delay so that the voltage can reach 5v. I believe that 50-100 ms is a good period. (if you are not in a hurry...)
The first command that we come across the initialization chart is the function set.

Function Set.

Image not found...

Bit0 and bit1 are ignored (This means that you can either write 0 or 1 to these bits.)
Bit2 to bit4 are the configurable bits for this command. Setting or clearing these bits you can either change :
* bit2 = Dot format (5x10 or 5x7)
* bit3 = Previewing lines (1 or 2)
* bit4 = Bus mode interface (8-bit or 4-bit),
Bit5 to bit7 must be left as it is in the command above, since this is the default setting to this command.

As it is shown in the chart, three times must be sent this command with the interval delays, to establish first an 8bit bus mode, (bit4 to bit7 are the critical)
and after that you resend the same command having cleared bit4 to establish a 4bit bus mode.
Now that 4-bit bus mode has been selected, it has only left to send once more the function set command (in two nibbles from now on) having set or cleared
the configurable bits to select the functions of the lcd as we have discussed above.
- An example : Sending b'0010 1000' will tell the lcd to enable 4-bit bus mode, have 2 lines preview, and the 5x7 dot format -

Display On / Off and Cursor.

Image not found...

The following command in the initialization chart is the display On/Off and cursor.
Bit0 to bit2 are the configurable bits for this command. Setting or clearing these bits you can either change :
* bit0 = Cursor blink (On-Off)
* bit1 = Cursor underline (On-Off)
* bit2 = Display (On-Off),
Bit3 to bit7 must be left as it is in the command above, since this is the default setting to this command.

Setting bit0 of this command you select the cursor of the lcd to blink. (This can be useful when you want to attract attention to a specific location on the lcd.)
Setting bit1 will occur every character that will be printed on the lcd to be underlined. (Personally i don't like that feature much)
Clearing bit2 will disable the lcd. (This feature can be really handy when power saving is necessary to your project.)

Clear Display.

Image not found...

One command before initialization ends, is the clear display.
In this command there are no configurable bits. You send it as it is by default.
This command clears the display (actually writes white spaces to all screen) and places the cursor to the first position of the lcd which is 0.
Also returns the display to its original state if it was shifted.
One very important thing that i must mention because was happened to me while i was experimenting with the lcd module, is that this command is not placed
in that initialization order by accident. After this command in the initialization chart comes the entry mode set.
As we will see furthermore the address counter increases or decreases automatically according your setup. But if the counter has been set to decrease instead of
increase, the clear display command will return the lcd to increase, since that is the default setting. So beware when using and where placing this command.

Character Entry Mode Set.

Image not found...

And finally the last command on initialization chart is the character entry mode set.
Bit0 and bit1 are the configurable bits for this command. Settiing or clearing these bits you can either change :
* bit0 = Display shift (On-Off)
* bit1 = Address counter (Increment - Decrement)
Bit2 to bit7 must be left as it is in the command above, since this is the default setting to this command

Setting bit0 of this command you'll make the display to shift. (But i will make further analysis later on.)
Setting bit1 will select lcd's address counter to increase.
These modules have a handy feature which is an internal counter, so you don't have to update counter's location in any character entry. (it does it automatically.)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These commands above are used for lcd's initialization. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Now let's see the remaining four...

Display and Cursor Home.

Image not found...

There is not much to say for this command just it places the cursor home to position 0 of lcd, without clearing it's contents.
Also returns the display to it's original state if it was shifted. As it is obvious in this command there are no configurable bits.
You send the command as it as it is by default. Bit0 is ignored so it can be either 0 or 1

Set CGRAM Address.

Image not found...

This command sets the address counter to write, in a specific location in the custom graphics ram (CGRAM), which is from 40h to 7Fh.
Bit0 to bit5 are the configurable bits for this command, where you tell the address counter to go and write in the specific address.
Bit6 and bit7 must be left as it is in the command above, since this is the default setting to this command.
Further analysis it can be found below on CGRAM chapter, where i explain how to read, write, and create custom graphics.

Set Display Address.

Image not found...

This command places the cursor to a selected address set by you, to print the character you want in that location.
The range for the address counter is from 80h to FFh.
Bit0 to bit6 are the configurable bits for this command, where you tell the address counter where to go and place the cursor,
and also to print the desired character.
Bit7 must be left as it is in the command above, since this is the default setting to this command.

Display / Cursor Shift.

Image not found...

With this command you can do two things.... The first one is that you can shift the display, or move the cursor. (Default)
The address counter moves the display or the cursor accordingly to the setting that it has been made
(increnment or decrement on 'Character Entry Mode Set' command).
And the second one is that you can control the direction when shifting the display, or moving the cursor to be left or right. (When it is enabled).
Bit0 and bit1 are ignored (This means that you can either write 0 or 1 to these bits.)
Bit2 and bit3 are the configurable bits for this command. Setting or clearing these bits you can either change :
* bit2 = Right Shift / Left Shift
* bit3 = Display Shift / Cursor move
Bit4 to bit7 must be left as it is in the command above, since this is the default setting to this command.
Shifting the display is a nice feature, because you can easily make scrolling messages that may look awesome to your projects.
Or if your imagination allows you... to create a mini game... ;-)
I will make a brief analysis below of how you can swift the display.


DDRAM (ROM) character table :

These lcd's have a rom inside them which holds the ASCII characters that can be printed on lcd...
There are some rom versions that vary on their stored ASCII. This is the standard rom version which includes some of my native
language alphabet letters (Greek) and some Japanese. Except the letters, roms have numbers and symbols as well.
These symbols can also vary in different roms versions.

Now let's see an example.... Let's say that you want to print the letter A (in capital).
The only thing that you have to do is revise this table, and see where this letter is stored in the internal rom.
As it is obvious capital A is stored in 41 (Hex) position. (Always upper bits first)
Then having set correctly the RS line to data mode, (RS=1) you send at first the upper byte '0100',
followed by the lower byte '0001' in two nibbles for 4-bit transmition mode.
However you can analyze my uploaded library to understand exactly how i manage to send characters and commands to the lcd
in 4-bit bus mode with the appropriate timings. I won't go in detail in this turorial of how i made my library.
Besides each individual programmer has his unique way of programming.

Image not found...
(Fig15)(Click to enlarge)

CGRAM (RAM) character table :

Image not found...
(Fig18) CGRAM block diagram
(Click to enlarge)
Having seen this table it is noticable that there are some places inside the chip's memory specified as CGRAM positions.
Here comes the good stuff... In these places you can actually create your own graphics.
(As i said before a bell, an hourglass, a heart or whatever comes to your imagination.)
Below on (Fig16) there is an example of a custom characters set i made.

On the character table above (Fig15) you can clearly distinguish the CGROM and CGRAM locations.
Locations from 20h to 7Fh correspond to letters, numbers and symbols of ASCII.
Locations from A0h to FFh correspond to symbols, and letters of Japanese and Greek alphabet.
Locations from 00h to 1Fh and 80h to 9Fh are reserved for the CGRAM.

According to hitachi's datasheet (Fig17) the CGRAM consists of 64bytes ram by 8-bit length per byte.
If you count the locations between 00h to 1Fh and 80h to 9Fh you will result the sum of 64bytes.
(Which correspond to the CGRAM locations inside the chip.)

In 5x8 display format, you can create 8 characters. (Since 8x8=64) and in 5x11 display format you can create 4 characters.
Only bit0 to bit4 will be used (See Fig18 on the right), leaving bit5 to bit7 to be discarded or ignored by the chip.
This is happening because display character length is 5-bits wide long. (5x8 or 5x11)

Image not found...
(Fig16) Previewing Custom characters.
(Click to enlarge)
Image not found...
(Fig17) Internal block diagram.
(Click to enlarge)

Looking (Fig18) on your right, i believe that it is more easier to understand how CGRAM generally works.
(Fig's18) left side is showing the "space" address occupied by CGRAM, which is from 40h to 7Fh.
These addresses in ram are called in command mode (RS=0) when you want to write in them.
The red arrows indicate the 8 call position addresses which are from 00h to 07h.
These addresses are called in data mode (RS=1) when you want to print the characters.
(If you click on the image, it will be enlarged and it will have better resolution than now.)
Finally on the right i have added the values in binary form, than hex, to be more visible the character.
So in order to create a custom character, you select the memory position that you would like to store it
from 40h to 7Fh and then you send the pattern for it, (8 bytes in a row). (More details in my library attachment)
After that you simply call the position which holds the character 00h to 07h, and it will be printed on the lcd....
Also locations from 00h to 07h are the same (duplicated, (corresponded to each other)) as 08h to 0Fh.

Polling or Delay ? Reading From Display

This is an interesting question that it's answer comes back with a counterquestion.... Are you in a hurry?
Actually there is only one way where you can check whether the lcd has finished processing the command or the data you have sent to it.
This is accomplished using Polling method.
Polling method, is a method that keeps checking lcs'd status register bit BF (Busy Flag) until it is cleared.
Delay on the other hand is as it sounds... A time delay with a predefined value set by you, according to the minimum time that each command
needs to be processed, as (Fig11) above illustrates.
Both methods have advantages and disadvantages that we will discuss later on.

Image not found...
(Fig18) Read instructions.
(Click to enlarge)
Reading is a completely different process than writing...
In order to read from the lcd you must first set R/W line, and after that there are two options
depending the state of the RS pin.
If you set RS pin, then data is returned from the lcd holding the character that it is at
the current cursor address
If you clear RS pin then lcd status is returned, holding the current cursor address from bit0 - bit6
leaving the remaining bit7 for the busy flag.

Prior sending commands for reading, microcontroller's outputs must switch over to inputs so we
would be able to read data. Apparently, lcd's inputs will become outputs and except 'bus contention',
damage to microcontroller may occur to its output pins.

So after that when 'tAS' (address set up) has elapsed, E line can be taken high.
The time that is needed to change lcd its outputs and stabilize the data, is a period of
320ns (Data access time 'tDA'). After that you can read the data and return pin E to low state.

Analyzing the advantages and the disadvantages i I believe it is now obvious that reading from lcd will became a headache in many ways...
Firstly the additional code that in some cases you are limited by microcontroller's memory.
The minus extra pin that it will be reserved for the R/W pin.
And finally the risk of lcd's hardware failure, that will occur microcontroller to stuck.
(However precautions can be taken to prevent a stuck, using an mcu hardware timeout such as watchdog)
The only advantage of polling method is the speed. That's why i asked at the beginning if you are in a hurry...
Otherwise delay is more preferable, simplier and flexible than polling. (Which is also the method is use in most applications.)

LCD Connections

Image not found...
(Fig19) Bus mode connections.
(Click to enlarge)

Fig19 above illustrates the two bus mode connections the 4-bit bus mode, and the 8-bit bus mode, also an alternative connection for the R/W pin.
In the 4-bit bus mode, data lines from 4 to 7 are used, leaving the other four 0 to 3 left open as hitachi suggest on the datasheet.
In the 8-bit bus mode, all data lines 0 to 7 are used.
If reading from the display is not required, then R/W pin can be tied to ground since writing to the display requires logic low.
(The alternative connection for R/W is used in delay method as we have described above.)

Image not found...
(Fig20) Contrast wiring.
(Click to enlarge)

There are three ways you can control the contrast of the lcd. Two analog and one digital.
To accomplish digital control contrast, you need the microcontroller to provide a square wave pwm signal with a duty cycle from 0 to 100%.
After that the signal is driven to a transistor amplifier and a low pass filter which converts the pwm signal into a voltage level.
When the duty cycle is 0% then the voltage level is high 5v and when the duty cycle is 100% then the voltage level is low 0V.

Another way is using a trimmer or a pontetiometer 5 to 10 kΩ to adjust the voltage that it is delivered to the input of the lcd thus it's contrast.
(Analog contrast control (1)). Αnd finally a fixed value resistor connected directly to ground. (Analog contrast control (2))

Due to temperature ambient variations, the contrast will change accordingly.
So the digital and the trimmer analog connections are preferable, since their adaptivity to adjust the contrast due to temperature more easily,
in comparison the resistor connection.

Swifting the Display / Cursor

Swifting the display is another cool feature that lcd modules have...
You can swift the display in both directions (left or right) but with a disadvantage.
The lcd moves all of its contents simultaneously in all lines.
That means that if you want to move a text on the first row (and lets say that the lcd has 4 rows),
you can't avoid moving the other rows with the same direction as well. Also be aware that when you shift the display,
the last character on each row, will roll over at the beginning of each row... (Examples below...)

Now... each time you send this command then the display or the cursor shifts left or right according to your settings.

Image not found...

I have made two examples in order to understand how swifting is working on lcd's..
One for 16x2 display and one for 16x1. It is now clearly how the display rolls over at the beginning.

Image not found...
(Fig21) Swifting Display Left / Right.
(Click to enlarge)