Вы находитесь на странице: 1из 15

1.

0 Introduction
LCD stands for Liquid Crystal Display. An LCD is a passive device. It does not produce any light and simply alters the
light travelling through it. With a voltage applied to it, the liquid crystal polarizes transmitted light in a different direction
to when no voltage is applied. A polarizing filter in front of the display then blocks one of the two polarizations (i.e. the
areas in which a voltage was applied or the ones where no voltage was applied) and therefore in some areas of the
screen appear black, this effect is used to draw the characters and graphics displayed by an LCD.

Reflective twisted nematic liquid crystal display


1. Polarizing filter film with a vertical axis to polarize light as it enters.
2. Glass substrate with ITO electrodes. The shapes of these electrodes will determine the shapes that will appear
when the LCD is turned ON. Vertical ridges etched on the surface are smooth.
3. Twisted nematic liquid crystal.
4. Glass substrate with common electrode film (ITO) with horizontal ridges to line up with the horizontal filter.
5. Polarizing filter film with a horizontal axis to block/pass light.
6. Reflective surface to send light back to viewer. (In a backlit LCD, this layer is replaced with a light source.)
Almost all LCDs have a strong light source built in behind a glass panel (which contains the liquid crystal), this ensures
that the areas of light and dark on the screen (dictated by the areas on the liquid crystal panel across which a voltage
is applied) have good contrast. Displays with no backlights that rely solely on the light incident on the LCD panel
cannot be used in low light conditions.
Most commonly used character based LCDs are based on Hitachis HD44780 controller or other which are compatible
with HD44580. In this tutorial, we will discuss about character based LCDs, their interfacing with PIC microcontrollers,
various interfaces (8-bit/4-bit), programming, special stuff and tricks you can do with these simple looking LCDs which
can give a new look to your application.
2.0 Pin Description
The most commonly used LCDs found in the market today are 1 Line, 2 Line or 4 Line LCDs which have only 1
controller and support at most of 80 characters, whereas LCDs supporting more than 80 characters make use of 2
HD44780 controllers.
Most LCDs with one controller have 14 pins or 16 pins (two extra pins are for back-light LED connections) while LCDs
with two controllers have two more pins to enable the additional controller. We will focus on LCDs with one controller in
this article since it is one of the commonly used models in the market. Likewise, the operations are applicable for two
controllers LCD as well. Pin description is shown in the table below.

Character LCD common pins diagram

Character LCD pins with one controller


The HD44780 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 (3 control lines plus the 4 lines for the data bus). If an 8-bit data bus is used the LCD will require
a total of 11 data lines (3 control lines plus the 8 lines for the data bus).
The three control lines are referred to as EN, RS, and RW.
The EN line is called Enable. This control line is used to tell the LCD that you are sending in data. To send data to
the LCD, your program should make sure this line is low (0) and then set the other two control lines and/or put data on
the data bus. When the other lines are completely ready, bring EN high (1) and wait for the minimum amount of time
required by the LCD datasheet (this varies from LCD to LCD), and end by bringing it low (0) again.
The RS line is the Register Select line. When RS is low (0), the data is to be treated as a command or special
instruction (such as clear screen, position cursor, etc.). When RS is high (1), the data being sent is text data which
sould be displayed on the screen. For example, to display the letter T on the screen you would set RS high.
The RW line is the Read/Write control line. When RW is low (0), the information on the data bus is being written to
the LCD. When RW is high (1), the program is effectively querying (or reading) the LCD. Only one instruction (Get
LCD status) is a read command. All others are write commandsso RW will almost always be low.
The data bus consists of 4 or 8 lines (depending on the mode of operation selected by the user). In the case of an 8bit data bus, the lines are referred to as DB0, DB1, DB2, DB3, DB4, DB5, DB6, and DB7.

Finally, the power supply pins for the backlight LED+ and LED-. Some LCD modules come without the backlight. In
that case, these pins are not found or are left disconnected. The recommended voltage for LED+ is 4.2V and LEDshould be connected to ground (GND). Vary the value of the resistor connected to LED+ will change the brightness of
the backlight. Normally, 220 Ohm or 330 Ohm resistor will be used. For advanced user, you may connect the pin to
PWM output and change the brightness in your software by altering the PWM duty cycle. We will further discuss this in
upcoming issues.
3.0 Hardware Connection
A typical LCD hardware connection to PIC microcontroller with backlight turned on permanently is shown in figure
below. To turn off the backlight, disconnect the supplies to pin 15 and 16. RB4, RB5 and RB6 of PIC16F877A are used
for the control signals while PORTD of the microcontroller is the data bus.

A typical LCD to PIC microcontroller hardware connection


4.0 DDRAM Display Data RAM
Display data RAM (DDRAM) stores display data represented in 8-bit character codes. Its extended capacity is 80 X 8
bits, or 80 characters. The area in display data RAM (DDRAM) that is not used for display can be used as general
data RAM. So whatever you send on the DDRAM is actually displayed on the LCD. For LCDs like 116, only 16
characters are visible, so whatever you write after 16 characters is written in DDRAM but is not visible to the user.
Figures below will show you the DDRAM addresses of 1 line and 2 lines LCDs.

5.0 CGROM Character Generator ROM


Now you might be thinking that when you send an ASCII value to DDRAM, how the character is displayed on LCD? So
the answer is in CGROM. The Character Generator ROM (CGROM) generates 58 dots or 510 dots character
patterns from 8-bit character codes (see figures below for more details). It can generate 208 58 dot character
patterns and 32 510 dot character patterns. User-defined character patterns are also available by mask-programmed
ROM. Here we will only discuss 58 dots character patterns LCD module which is commonly used.

LCD characters code map for 58 dots


As you can see in both the code maps, the character code from 000 to 007 is occupied by the CGRAM characters
or the user defined characters. If user wants to display the fourth custom character then the code to display it is 003
i.e. when user sends 003 code to the LCD DDRAM, the fourth user created character or pattern will be displayed on
the LCD.
6.0 CGRAM Character Generator RAM
As indicated by its name, CGRAM area is used to create custom characters in LCD. In the character generator RAM,
user can rewrite character patterns by program. For 5 x 8 dots, eight character patterns can be written, and for 5 x 10
dots, four character patterns can be written. We will not cover how to use CGRAM area to make custom characters in
this tutorial. Please stay tune for the future issue.
7.0 BF Busy Flag
Busy Flag is a status indicator flag for LCD. When we send a command or data to the LCD for processing, this flag is
set (i.e BF =1) and as soon as the instruction is executed successfully this flag is cleared (BF = 0). This is helpful in
determining the exact amount of delay for the LCD process.
To read Busy Flag, the condition RS = 0 and R/W = 1 must be met and the MSB of the LCD data bus (D7) acts as
busy flag. When BF = 1 means LCD is busy and will not accept next command or data and BF = 0 means LCD is
ready for the next command or data to process.
8.0 Instruction Register (IR) and Data Register (DR)
There are two 8-bit registers in HD44780 controller Instruction and Data register. Instruction register corresponds to
the register where you send commands to LCD e.g LCD shift command, LCD clear, LCD address etc. and Data
register is used for storing data which is to be displayed on LCD. When send the enable signal of the LCD is asserted,
the data on the pins is latched in to the data register and data is then moved automatically to the DDRAM and hence is
displayed on the LCD. Data Register is not only used for sending data to DDRAM but also for CGRAM, the address
where you want to send the data, is decided by the instruction you send to LCD. We will discuss more on LCD
instruction set further in this tutorial.
9.0 LCD Commands and Instruction Set
Only the Instruction Register (IR) and the Data Register (DR) of the LCD can be controlled by the MCU. Before
starting the internal operation of the LCD, control information is temporarily stored into these registers to allow

interfacing with various MCUs, which operate at different speeds, or various peripheral control devices. The internal
operation of the LCD is determined by signals sent from the MCU. These signals, which include register selection
signal (RS), read/write signal (R/W), and the data bus (DB0 to DB7), make up the LCD instructions. There are four
categories of instructions:

Designate LCD functions, such as display format, data length, etc.

Set internal RAM addresses

Perform data transfer with internal RAM

Perform miscellaneous functions

Commands and Instructions set for LCD type HD44780


Although looking at the table you can make your own commands and test them. Below is a brief list of useful
commands which are frequently used while working on the LCD.

Frequently used commands and instructions


for LCD
The table above will help you while writing programs for LCD. But after you are done testing with it, I recommend you
to use the previous table (Commands and Instructions set for LCD type HD44780) to get more grip on working
with LCD and trying your own commands.
9.0 Conclusion
Thats all for this issue. In the next part of the tutorial we will continue with the software programming for PIC
microcontrollers to interface with the LCD module. Please continue to follow this topic and let your application interacts
with you through LCD!

LCD Initialization
In this part, we will see the initialization with some of the coding examples in C using Microchip MPLAB IDE and HITECH C PRO compiler for the PIC10/12/16 MCU Family. These software are free of charge and the latest releases
can be obtained from both Microchip and HI-TECH websites.
Before using the LCD for display purpose, LCD has to be initialized either by the internal reset circuit or sending set of
commands to the LCD. User has to decide whether an LCD has to be initialized by instructions or by internal reset
circuit. We will discuss both types of initialization here.
Initialization by Internal Reset Circuit
An internal reset circuit automatically initializes the HD44780U when the power is turned on. The Busy Flag (BF) is
kept in the busy state until the initialization ends (BF = 1). The busy state lasts for 10ms after VCC rises to 4.5V. The
following instructions are executed during the initialization.

Display clear

Function set:
DL = 1; 8-bit interface data
N = 0; 1-line display
F = 0; 5 x 8 dot character font

Display on/off control:


D = 0; Display off
C = 0; Cursor off
B = 0; Blinking off

Entry mode set:


I/D = 1; Increment by 1
S = 0; No shift

There are certain conditions that have to be met, if user wants to use initialization by internal reset circuit. These
conditions are shown in the table below.

Power supply conditions using internal reset circuit


Figure below shows the test conditions which are to be met for internal reset circuit to be active.

Internal power supply reset


The problem with internal reset circuit is that it is highly dependent on power supply. It is not hard to meet this critical
power supply conditions but it is often difficult to achieve when simple application are involved. Hence, usually the
second method, initialization by instruction is used and is recommended most of the time.
If the electrical characteristics conditions listed under the table Power Supply Conditions using Internal Reset Circuit
are not met, the internal reset circuit will not operate normally and will fail to initialize the HD44780U. For such a case,
initialization must be performed by the MCU as explained in the next section, Initializing by Instruction.
Initialization by Instructions
Initializing LCD with instructions is relatively simple. Given below is a flowchart that describes the step to follow to
initialize the LCD.

Flow chart for LCD 8-bit interface initialization


The first 3 commands are usually not required but are recommended when you are using 4-bit interface. So actually
you can program the LCD starting from sending function set when working with 8-bit interface. Function set command
depends on what kind of LCD you are using and what kind of interface you are using (refer to the table in LCD
Command section).
For PIC16F877A, the typical configuration settings and the declaration of LCD pins are shown in the figure below.

A typical configuration settings and declaration of LCD pins for PIC16F877A


LCD Entry Mode
From Commands and Instructions set for LCD type HD44780 table attached at the end of this article, you can
see that there are two bits which determine the entry mode for LCD:
a) I/D Increment/Decrement bit
b) S Display shift.
Since bit 2 is always set, we get four combinations of entry mode which are 004 (100 2), 005 (1012), 006 (1102) and
007 (1112). So we get different results with these different entry modes. Normally entry mode 006 is used, which is
no shift and automatic increment. Do try all the possible entry modes and see the results, I am sure you will be
surprised.

Programming example for LCD Initialization in C Language


With the help of the above code, you are able to initialize the LCD. The sample code contains a function/subroutine
LCD_busy. This subroutine is used to call for delay so that there should not be any command or data sent to the LCD
until it finishes executing the command. More on this delay routine is explained in the next section.
Checking the Busy Flag
As discussed in the previous section, there must be some delay which is needed to be there for LCD to successfully
process the command or data. So this delay can be made either with a delay loop of specified time more than that of
LCD process time or we can read the busy flag, which is recommended. The reason to use busy flag is that delay
produced is almost the amount of time for which LCD need to process. So, it is best suited for every application.
Steps to Read Busy Flag
When we send the command, the BF or DB7 bit of the LCD becomes 1 and as soon as the command is processed the
BF = 0. Following are the steps to be kept in mind while reading the Busy flag.

Select command register

Select read operation

Send enable signal

Read the flag

So following the above steps we can write the code in C as below

LCD Busy Flag routine in C Language


If you do not want to read the busy flag you can simply use delay routines to provide the specific amount of delays.
You have to make sure the delays are reasonable by referring to Commands and Instructions set for LCD type
HD44780 table. The example code can be obtained at Cytrons SK40C (Enhanced 40 pins PIC Start-up Kit) product

page. Busy flag cannot be checked when you are using SK40C because the R/W (Read/Write) pin of LCD is
connected to Ground permanently. So read command is unable to be executed and delay routines must be used for
the LCD functions. The main reason to have such design is to reserve more PIC I/O pins for other applications.
It is often important to initialize the function or uses function prototypes at the beginning of the program (please refer to
source code provided here: www.robothead2toe.com.my)
Now that we are ready with the initialization routine and the busy routine for LCD, well move on to the next section on
how to send data and command to the LCD.
Sending Commands to LCD
In order to send commands we simply need to select the command register. Everything is same as we have done in
the initialization routine. But we will summarize the common steps and put them in a single subroutine. Following are
the steps:

move data to LCD port

select command register

select write operation

send enable signal

wait for LCD to process the command

Keeping these steps in mind we can write LCD command routine as:

Routine for LCD send command in C language


Setting Cursor Position on LCD
To set the cursor position on LCD, we need to send the DDRAM address.
Bit
7
6
5
4
3
2
1
0
Value 1
AD6
AD5
AD4
AD3
AD2
AD1
AD0
DDRAM address
The seventh bit is always 1, and bits 0 to 6 are DDRAM address (refer the LCD Commands and Instruction Set
section). So if you want to put the cursor on first position the address will be 0000000 in binary and 7th bit is 1. The
address will be 100000002 or 080, so for DDRAM all address starts from 080.
For 2 lines and 16 characters LCD. The address from 080 to 0x8F are visible on first line and 0xC0 to 0xCF is visible
on second line, the rest of the DDRAM area is still available but is not visible on the LCD, if you want to check this
thing, then simply put a long sting greater than 16 character and shift the entire display, you will see all the missing
character coming from the back. By this way you can create scrolling line on LCD (see more on shifting display
in commands section).
Below is an example for setting cursor position on LCD:

An example for setting cursor at first line, 4th position


Sending Data to LCD
In order to send data we simply need to select the data register. Everything is same as the command routine.
Following are the steps:

move data to LCD port


select data register
select write operation
send enable signal
wait for LCD to process the data

LCD send data routine in C language


You have seen that its really easy to send command and data to LCD. What if we have a string to send to LCD? Its
simple. We will store the LCD string in the ROM of the PIC microcontroller and call the string character by character. A
simple example is shown below.

LCD send string routine in C language


Conclusion
If you have been following this article until this stage, you should be able to configure and display characters on your
LCD module using a PIC microcontroller. Have fun! The full sample source code can be obtained from Robot. Head to
Toe website (www.robothead2toe.com.my). Please follow us in the next issue for more explanation on the
advanced features of the LCD, such as creating custom characters and 4-bit data bus interfacing.

Revision
General information of the LCD, circuit connection to PIC microcontroller, software initialization,
commands and instruction sets, and the basic sample program have been discussed in the previous
issues. With all that, you can display anything you want on the LCD, but it has to be based on the
predefined characters. So this tutorial is drafted to show you how to make use of the CGRAM of the LCD
to create your own characters or patterns. Hence you can display more interesting stuff on your LCD!

Character Generator Random-Access Memory (CGRAM)


All character based LCD of type HD44780 has CGRAM. In order to create custom patterns, we need to
store values to the CGRAM defining which pixel to glow. From the figure shown below, 6 bits address
from
DB0
to
DB5
(ACG)
is
used
to
access
64
bytes
of
CGRAM
area.

Figure: CGRAM command and address.


When you are using 58 dots LCD with 64 bytes of data space, you can define a total of 8 user defined
patterns. Although one row is consisting of 5 pixels, one byte is needed for each row and 8 rows are

needed to complete each pattern. When LCD is working in 510 dots, you can only create 4 user
defined patterns. However, we will only discuss 58 dots LCD type in this article. The figure below
shows the typical 58 dots LCD pixel map for a single character.
Figure: A typical 58 dots character pixel
map showing L.

CGRAM Address
The memory map of the 8 user defined
characters is given in the table below. The
first character will occupy 8 bytes, starting
from 000, until 007. Then the next
character starts at 008 and ended at 0x0F. This trend continues until the end of the CGRAM address,
which
is
0x3F.
Pattern
0
1
2
3
4
5
6
7

CGRAM Address (ACG)


000 007
008 0x0F
010 017
018 0x1F
020 027
028 0x2F
030 037
038 0x3F

Table: CGRAM memory map.


By referring to the first figure (CGRAM command and address), since bit 6 (DB6) is always 1 and bit 7
(DB7) is always 0, we can point to certain CGRAM address by sending the sum of CGRAM address
(ACG) and 040 (0b01000000). For example, we send the command as 048 (= 008 + 040) to
point the cursor to the CGRAM address of pattern 1. In other words, although 008 is the actual CGRAM
address, we need to send the code 048 to the LCD module to produce the correct result. Examples
are given in the table below. You will notice that the hexadecimal codes are actually the sum of 040
and
the
CGRAM
addresses
in
the
previous
table.

Pattern
0
1
2
3
4
5
6
7

Fixed
DB7
DB6
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1

Binary Code (0bxxxxxxxx)


CGRAM Address
DB5
DB4
DB3
DB2
DB1
0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
1
1
0
0
1
0
0
0
0
1
0
1
0
0
1
1
0
0
0
1
1
1
0
0

Hexadecimal Code
DB0
0
0
0
0
0
0
0
0

040
048
050
058
060
068
070
078

Table: Examples of the CGRAM address and the combined code.

Creating Custom Character


Lets take a look at how a custom character is defined. There are many free LCD character generator
programs, such as LCD Express for AVR microcontroller designed by Vega-XP and the online CustomCharacter Generator hosted by Scott Edwards Electronics Inc. Those programs are really helpful but I
personally prefer to use the manual method. This is because most of the programs give you the

hexadecimal value for each row of pixels, but the simplest way is to look into the binary value.
All we have to do is make a pixel-map of 58 and get the binary value for each row. A bit value is 1 if
the pixel is glowing and the bit value is 0 if that pixel is off. Ill use a smiley J pattern to further explain
it. The figure shows my version of smiley face. It may look less smooth due to the limited pixels
available but I believe you can recognize the happy face with a pair of eyes and the raised mouths
corners.

Figure: Smiley pattern with the corresponding binary value for each row.
The last row is usually left blank (0b00000000) for the cursor. If you are not using cursor, you can also
make use of that row 7. This will give you more pixels for one pattern. Now we have the values for each
row to create a smiley pattern. As you can see in the table below, the binary value can be used directly
as the argument for LCD_senddata( ) function. We only need to add 0b in front of each value to
declare
that
it
is
a
binary
value.
Row
0
1
2
3
4
5
6
7

CGRAM data (binary value)


00000000
00001010
00001010
00000000
00010001
00001110
00000000
00000000

Argument x in lcd_senddata(x)
0b00000000
0b00001010
0b00001010
0b00000000
0b00010001
0b00001110
0b00000000
0b00000000

Table: Translation of CGRAM Address to the argument for LCD_senddata( ) function.

C Programming
Lets say if we want to write the smiley pattern at pattern location 1. So we send the command as 048
(= 040 + 008), and then we send the pattern data. The details description LCD_command( ) and
LCD_senddata( ) subroutines is mentioned in LCD Interfacing with PIC Microcontrollers (Part 2). Below
is
the
C
code
to
do
this.

Figure: C code to save custom character to pattern location 1.


To save all 8 custom characters at once, we can send the cursor to the beginning of the CGRAM
address, which is 040. Then the data of the 8 patterns are sent byte-by- byte until all 64 bytes of
CGRAM have been written. This is shown in the sample program given. It will be uploaded to Robot
Head
to
Toes
website,
Downloads
section.
The above figure shows the routine to create smiley character at pattern location 1. To display the
above defined pattern on LCD, simply call LCD_senddata(1), where 1 in the subroutine function is the
argument
to
indicate
pattern
1.
This
is
shown
in
the
C
code
below.

Bottom of Form
Figure: C code to display the user defined character, pattern 1.
More examples of custom characters are shown in the figure below. As you can see, we can even
combine
two
standard
characters
into
one
58
dots
frame
too.

Figure: More example of custom characters or patterns.

Conclusion
The tutorial on custom character ends here. Hope you enjoy creating your own custom characters. We
will continue our discussion on LCD backlight power saving method in the next issue.

Вам также может понравиться