Home

PIC Resources

PIC
Introduction

PIC
ICSP

PIC
Programmer Types

PIC

Ultrasonic
Distance Meter

Clock
DS1307

Volt
Meter

More
PIC Projects...

Arduino

Humidity
DHT22

Temperature
DS18B20

8x8
LED matrix MAX7219

MAX6675
0°C to 1024°C

Pulse
Rate Sensor

Hitachi
HD44780 LCD

Logic
Level Converter

SSD1306
OLED

BMP280
Pressure

Resources

Project
Ideas

Tips
& Techniques

PIC
Tutorials

Microcontroller
Blog

Site
map.

PIC C Course
- 25% Off

18F
Training

Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and
other free resources.

Name:

E-Mail:

Don't
worry -- youre-mail address is totally secure. I promise to use it
only to send you
MicroZine.

Using the Hitachi
HD44780 with the Arduino

The Hitachi HD44780 is an LCD driving chipset usually driving a 2 line by 16
character display. You can get many different screen sizes e.g. 16x4, 20x4,
80x1. Regardless of that, the chipset, and hence the driving software remains
the same.

These type of displays are very low cost and can display any ASCII text that
you want. In addition you can also generate your own characters. Using these it
is possible to create a simple bar graph to display a graphical representation
of voltage etc.

The most common type of HD44780 display is a 2 line, 16
character LCD display.

The rear view of a Hitachi HD44780 module:

Hitachi HD44780 4 bit mode

The HD44780 is capable of operating in 8 bit mode i.e. faster (but see
below), but that means you need 11 microcontroller pins. It is a trade off
between speed and number of microcontroller pins you have available. In fact
speed is not really that important as the amount of data needed to drive the
display is low and the timing of the HD44780 interface means there are lots of
37us delays needed anyway (after a command is written). The liquidCrystal
library uses 100us to be on the safe side. Note One command: clear display
takes 2ms.

The 4 bit mode is more appropriate for microcontrollers since you only need
about 6 pins. Inside the HD44780 you still have 8 bit operation so for 4 bit
mode you do two writes to get that 8 bit quantity inside the chip.

Connections to
the Hitachi HD44780 in 4 bit mode.

The circuit is quite simple and here only 6 wires are used for the
HD44780:

RS - register select (Selects the data or instruction register inside the
HD44780).

E - enable (This loads the data into the HD44780) - on the falling
edge.

D4 - Part of upper nibble used in 4 bit mode.

D5 - Part of upper nibble used in 4 bit mode.

D6 - Part of upper nibble used in 4 bit mode.

D7 - Part of upper nibble used in 4 bit mode.

There is also a 10k pot across the supply and connected to Vo of the
LCD.

The backlight led has a 470R resistor connected to 5V and to pin A of the
LCD.

Pin K of the LCD is connected to GND.

Add a decoupling capacitor across Vcc and GND
(not shown in photos).

Connections
to the Arduino are:

Arduino Connections

LCD Name

Arduno pin

RS

5

E

4

D4

3

D5

2

D6

1

D7

0

5V

Arduino 5V

GND

Arduino GND

Warning Some HD44780 Displays have the 16 connection pins
on lower edge of the pcb - so you might get it upside down - It is probably best
if to test out the display on a solderless breadboard if unsure of the display
orientation.

Photo of Arduino Connections

The following picture shows the HD44780 display connections operating in 4
bit mode:

Note: The chip shown on the left is not
used (yet)- it is a 74HC595 ready for testing serial mode. In the next page this
device is used to reduce the number of pins from the Arduino.

Connections are as follows:

Arduino Hitachi HD44780 display: 4 bit mode
connections

Description

Wire col

RS

Brown

E

Blue

D4..D7

Grey

10k pot - wiper to Vo

Yellow

Vcc, Vdd (5v)

Orange

GND

black, brown

470R

To LCD backlight Anode

Software Library and versions

Arduino IDE Version

Version : 1.6.4

Hitachi HD44780 Liquid
Crystal Library

The library used here is LquidCrystal 1.01 - you can easily install it from
the Arduino IDE.

If you do not see the library as an entry when you click the menus:

Sketch-->Include Library

Then select manage libraries :

Sketch-->Include Library -->Manage
Libraries...

Search for and install LiquidCrystal using the "Filter Your Search" form.

Hitachi HD44780 Example 1 : 4bit
parallel mode

This is a simple example. Note how the main loop has no code since we only
want to initialise and display the text without doing anything else.

Copy
Sketch

#include <LiquidCrystal.h>

#define LCD_RS 5 // Register select
#define LCD_E 4 // Enable
#define LCD_D4 3
#define LCD_D5 2
#define LCD_D6 1
#define LCD_D7 0

// * LCD R/W pin to ground
// * 10K pot:
// * ends to +5V and ground
// * wiper to LCD VO pin (pin 3)
// A Anode Backlight R (~470R) to Vdd
// K kathode to GND, VSS = GND, Vdd = 5V.

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd( LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void setup() {
lcd.begin(16, 2); // set up the LCD's columns and rows
lcd.print("How to Drive an");
lcd.setCursor(0, 1);
lcd.print("HD44780 16x2 LCD");
}

void loop() {

}

Hitachi HD44780
Common LiquidCrystal Commands

The Hitachi HD44780 has many commands, Here are the most useful:
initialisation, xy location setting and print:

Class instantiation intialisation

LiquidCryslal< object>
(pins...)

This instantiation process also intialises the pins
in use

Public class functions

begin(16,2)

Tell the software what display you have - must be
called before other commands.

setCursor(x,y)

Top left is (0,0)

print(data[ ,base]) - [] optional

This is an overloaded function that can print any
of the three number types or a string. If you use a number char,byte,int or
long) you can also choose which base it is converted into using three letter
acronyms, BIN, DEC, OCT, or HEX.

One other function that is useful is the user generated character
function:

createChar(uint8_t addr, uint8_t
data[]);

This defines the data for use as user generated
character.

Object Instantiation and
function use

An object is created using the main class constructor (in this case
LiquidCrystal) as follows (here the object created is labeled lcd):

LiquidCrystal lcd(LCD_RS,LCD_E,LCD_D4,LCD_D5,LCD_D6,LCD_D7);

Note: This is also used to initialise internal
data structures with the pins in use.

Once created, you can access the class library functions with the
instantiated object (lcd) followed by a period and then the public class
function: So, to print out some text for the lcd object (above)you would
type:

lcd.print("My
text");

As noted above this function is overloaded to allow number output:

lcd.print((char)35,BIN);

Hitachi HD44780
LiquidCrystal Commands

Here's a full list of the LiquidCrystal public library commands for the
Hitachi HD44780 :

public:
LiquidCrystal(uint8_t rs, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
LiquidCrystal(uint8_t rs, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

The above object creators (constructor prototypes) differ only in the number of
parameters. For example the first and second differ only in that the 1st one does
not have the rw variable, and both operate the 8 bit interface. Then next two
again only differ in the rw variable and operate the 4 bit interface.

All these constructors are guided in code to call the "init" function below (look
for a magic number in the library source code that indicates when rw is not to
be used (it is 255)).

void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);

The following function allows the underlying functions to know how big your
display is and whether a large font is in use.

void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

The following fuctions are self-evident, taking no arguments:

void clear();
void home();

void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void leftToRight();
void rightToLeft();
void autoscroll();
void noAutoscroll();

The y position of the display is often strange for larger displays as two
HD44780's are used so the start address for each row needs to be set (in some
cases).

void setRowOffsets(int row1, int row2, int row3, int row4);
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
virtual size_t write(uint8_t);

This one is a little different as it uses the print class. That is one good thing
about OOP. In this case the serial print class allows you to re-write the "write"
function that actually accesses the hardware. So instead of directing the serial
data to the serial port you can re-direct the data to the LCD but retain all the
number formatting code!

using Print::write;

Arduino Code Operation

While reviewing the operation of the LCD code I found this interesting
snippet:

void LiquidCrystal::write4bits(uint8_t value) {
for (int i = 0; i < 4; i++) {
pinMode(_data_pins[i], OUTPUT);
digitalWrite(_data_pins[i], (value >> i) & 0x01);
}
pulseEnable();
}

There's nothing wrong with the code but it has to do a lot of manipulation to
make the operation generic. It shows how that to make code generalised and easy
to use there is a sacrifice in performance. There are two interesting parts to
this operation

pin mode setting.

data manipulation to output.

First of all the pin mode is set every time that a write is made to the LCD.
This would ensure that if other code accidentally set the pin direction wrongly
then this would override it. Usually a port is dedicated to one operation so
pin modes should be set in the "setup" routine. The way it is done here is
"safe" but gives a big performance hit at each lcd write operation..

Secondly to manipulate each data bit to direct it to the output takes a few
operations involving selecting the pin and then shifting the value right. It's
clever and works in all cases but again there is a performance hit. By using
the hardware in a straight forward way then you can avoid this coding i.e. use
the lower 4 bits of an output port and and you only need a few bit manipulation
operations: a lower four bit and mask:

port_val &= 0xf0; // Clear
the lower bits

port_val |= low_nibble &
0x0f; // Setup the low output nibble

op_port = port_val; // Send the
new data to the port.

For arduino operation, performance is not as important as speed and ease of
coding and it allows users to mix and match code to get it working but you
should be aware that underneath all the magic there can be a lot going on and
you could re-write it (or re-wire the hardware) for better performance.

Hitachi
HD44780 Example 2 : Time since last reset.

The following example uses the print command to continuously output an
updated time display every 99ms.

Copy
Sketch

#include <LiquidCrystal.h>

#define LCD_RS 5 // Register select
#define LCD_E 4 // Enable
#define LCD_D4 3
#define LCD_D5 2
#define LCD_D6 1
#define LCD_D7 0

// * LCD R/W pin to ground
// * 10K pot:
// * ends to +5V and ground
// * wiper to LCD VO pin (pin 3)
// A Anode Backlight R (~470R) to Vdd
// K kathode to GND, VSS = GND, Vdd = 5V.

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd( LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void setup() {

lcd.begin(16, 2); // set up the LCD's columns and rows
lcd.clear();
lcd.print("Time:");
lcd.setCursor(0,1);
lcd.print("Time from reset.");
}

long countTime = 0;
long oldTime = 0;

void loop() {

delay(1);
countTime += 1;

if (millis()-oldTime>99) { // update every 99ms
lcd.setCursor(5,0);
lcd.print(countTime,DEC);
oldTime=millis();
}
}

Hitachi HD44780 Example 3 : Custom
Character bar

The user defined characters will be updated to give a graphical display - a
moving bar that represents increments of 1/4 of a second. You could represent
any analogue quantity with this code..

Each character is 5 pixels wide and there are 16 characters to a row so there
are a total of 16x5 = 80 pixels across the display. You can use this information
to display a horizontal bar graph.

Note: You can use as many pixels as you want as the bar drawing routine uses
x,y (LCD coordinates) to start from, and then just a number representing the
number of pixels to draw to the right.

Copy
Sketch

#include <LiquidCrystal.h>

#define LCD_RS 5 // Register select
#define LCD_E 4 // Enable
#define LCD_D4 3
#define LCD_D5 2
#define LCD_D6 1
#define LCD_D7 0

byte cc[8]; // Custom Character

// * LCD R/W pin to ground
// * 10K pot:
// * ends to +5V and ground
// * wiper to LCD VO pin (pin 3)
// A Anode Backlight R (~470R) to Vdd
// K kathode to GND, VSS = GND, Vdd = 5V.

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd( LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

// 0 is the full block character
// 1 has left bar filled
// 2 has 2 left bars filled
// ...
// 4 has 4 left bars filled.
void createBarChars(void) {
byte mask = 0x10;
byte current=0;
for (int cgchar=1; cgchar<=4; cgchar++) {
current |= mask;
mask=mask>>1;
for (int i=0; i<8; i++) cc[i]=current;
lcd.createChar(cgchar, cc);
}
for (int i=0; i<8; i++) cc[i]=0x1f; // Create full block.
lcd.createChar(0, cc);
}

void drawBar(byte x, byte y, byte pixels) {
int i;
byte blocks = pixels / 5; // 5 pixels wide per character.
byte rem = pixels % 5;
for (i=0;i<blocks;i++) {
lcd.setCursor(x+i,y);
lcd.write(byte(0));
}
lcd.setCursor(x+i,y);
if (rem!=0) {
lcd.write(rem);
}
}

void setup() {

lcd.begin(16, 2); // set up the LCD's columns and rows
lcd.clear();
lcd.print("Time:");

createBarChars();
}

long countTime = 0;
long oldTime = 0;

void loop() {
static int idxcg = 0;

delay(1);
countTime += 1;

if (millis()-oldTime>99) { // update every 99ms
lcd.setCursor(5,0);
lcd.print(countTime,DEC);
oldTime=millis();

if ((countTime/250)%80==0) { // Clear Bar Area.
lcd.setCursor(0,1);
lcd.print(" ");
}
drawBar(0,1,(countTime/250)%80); // parameter update is quarter seconds.
}
}

Show Index

×

Using
the Hitachi HD44780 with the Arduino
Hitachi
HD44780 4 bit mode
Connections
to the Hitachi HD44780 in 4 bit mode
Photo
of Arduino Connections

Software
Library and versions
Arduino
IDE Version
Hitachi
HD44780 Liquid Crystal Library

Hitachi
HD44780 Example 1

Hitachi
HD44780 Common LiquidCrystal Commands

Object
Instantiation and function use
Hitachi
HD44780 LiquidCrystal Commands

Arduino
Code Operation

Hitachi
HD44780 Example 2

Hitachi
HD44780 Example 3

New! Comments
Have your say about what
you just read! Leave me a comment in the box below.

Privacy
Policy | Contact
| About
Me

Site
Map | Terms
of Use

Home

Projects

Arduino

MAX7219
Dotmatrix

MCP23017
I/O Expander

BMP280
Pressure Sensor

DS18B20
Thermometer

Humidity
DHT22/11

Rotary
Encoder

MAX6675 0 to
1024 DegC

Battery
Charger

SSD1306
OLED

74HC595 I/O
Expander

Hitachi
HD44780

Logic
Level Converter

DigitalWrite

Ebooks

Digital
download eBooks

PIC

LED
Dot Matrix 8x8 Direct drive

Serial
LCD

LCD
Keypad

Frequency
Counter LCD

Frequency
Counter 7seg

DS1307
Clock

Binary
Clock 8x8 matrix

Infrared
Receiver

A PIC
12F675 tutorial.

LCD
Volt Meter

PIC
Sonar

PIC
Projects

Project
Ideas

Interfaces

SPI
Interface

I2C
Interface

PIC Resources

PIC
Introduction

PIC
ICSP

Programmer
Types

Resources

Tips &
Techniques

PIC
Tutorials

Microcontroller
Blog

Site
map

Other

Articles

Books

report
this ad

report
this ad

Visit our Facebook Page:
To Visit Click Here

Recent
Articles

PCF8591: An
8 bit ADC you can easily connect using I2C

PCF8591: A four input ADC with single DAC. How
good is this 8 bit ADC, and should you use it in your next project?

Read
more

AD9833
a versatile easy to use signal generator on a chip

Find out how to use the AD9833 to generate sine,
square and triangle waves at 0.1Hz resolution.

Read
more

How
to use an arduno Nano as an ISP (In System Programmer)

Arduino Nano ISP: How to program an ATmega328P
using an Arduino Nano as the ISP programmmer. One common problem: Programming
a sketch into the chip without a reset control - solved here.

Read
more

Arduino
Voltage Reference Capabilities

Arduino Voltage reference: Both the Uno and Nano
have a built-in voltage reference: Find out how to make it more accurate. In
addition find out how to use it to measure the supply voltage 1V8 ~ 5V5

Read
more

Arduino
EEPROM - how it works and how to use it - with examples.

Arduino EEPROM: How to use it and How to preserve
the life of EEPROM. Two examples sketches to save multiple values to
EEPROM.

Read
more

How
to use the ADS1115

A tutorial on using the ADS1115 precision 16 bit
ADC for low power use.

Read
more

Readers
Comments

"I wanted
to thank
you so so so much
for all the information
you have
provided in
your site it's

SUPERB and
FANTASTIC."

- Ranish Pottath

"This
site really is
the best and my favorite.
I find here many useful

projects and tips."

- Milan

bursach<at>gmail.com<

"Awesome
site,
very, very easy and nice
to navigate!"

- Matt

matt_tr<at>
wolf359.cjb.net

Learn Microcontrollers

"Interested
in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE

"I
am a newbie to PIC
and I wanted to say
how great your
site has
been for me."

- Dave

de_scott<at>bellsouth.net

"Your
site is a great
and perfect work.

congratulations."

- Suresh

integratredinfosys<at>
yahoo.com

"I
couldn't find the correct
words to define
yourweb site.

Very
useful, uncovered,
honest and clear.

Thanks so much for
your time
and works.
Regards."

- Anon

report
this ad

Back
to Top

Copyright © 2005-

Best-Microcontroller-Projects
All Rights Reserved.
No reproduction
without permission.

x

x