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
7
E
6
D4
5
D5
4
D6
3
D7
2
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
RW
GND (black)
D4..D7
Grey
10k pot - wiper to Vo
Yellow
Vcc, Vdd (5v)
Orange
GND (Vss)
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.
#include<LiquidCrystal.h>
#defineLCD_RS7// Register select
#defineLCD_E6// Enable
#defineLCD_D45#defineLCD_D54#defineLCD_D63#defineLCD_D72
// * 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
LiquidCrystallcd(LCD_RS,LCD_E,LCD_D4,LCD_D5,LCD_D6,LCD_D7);
voidsetup(){
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");
}
voidloop(){
}
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):
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_trs,uint8_tenable,
uint8_td0,uint8_td1,uint8_td2,uint8_td3,
uint8_td4,uint8_td5,uint8_td6,uint8_td7);
LiquidCrystal(uint8_trs,uint8_trw,uint8_tenable,
uint8_td0,uint8_td1,uint8_td2,uint8_td3,
uint8_td4,uint8_td5,uint8_td6,uint8_td7);
LiquidCrystal(uint8_trs,uint8_trw,uint8_tenable,
uint8_td0,uint8_td1,uint8_td2,uint8_td3);
LiquidCrystal(uint8_trs,uint8_tenable,
uint8_td0,uint8_td1,uint8_td2,uint8_td3);
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)).
voidinit(uint8_tfourbitmode,uint8_trs,uint8_trw,uint8_tenable,
uint8_td0,uint8_td1,uint8_td2,uint8_td3,
uint8_td4,uint8_td5,uint8_td6,uint8_td7);
The following function allows the underlying functions to know how big your display is and whether a large font is in use.
voidbegin(uint8_tcols,uint8_trows,uint8_tcharsize=LCD_5x8DOTS);
The following fuctions are self-evident, taking no arguments:
voidclear();
voidhome();
voidnoDisplay();
voiddisplay();
voidnoBlink();
voidblink();
voidnoCursor();
voidcursor();
voidscrollDisplayLeft();
voidscrollDisplayRight();
voidleftToRight();
voidrightToLeft();
voidautoscroll();
voidnoAutoscroll();
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).
voidsetRowOffsets(introw1,introw2,introw3,introw4);
voidcreateChar(uint8_t,uint8_t[]);
voidsetCursor(uint8_t,uint8_t);virtualsize_twrite(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!
usingPrint::write;
Arduino Code Operation
While reviewing the operation of the LCD code I found this interesting
snippet:
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 LCDwrite 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:
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.
#include<LiquidCrystal.h>
#defineLCD_RS7// Register select
#defineLCD_E6// Enable
#defineLCD_D45#defineLCD_D54#defineLCD_D63#defineLCD_D72
// * 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
LiquidCrystallcd(LCD_RS,LCD_E,LCD_D4,LCD_D5,LCD_D6,LCD_D7);
voidsetup(){
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.");}
longcountTime=0;
longoldTime=0;
voidloop(){
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 column 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.
#include<LiquidCrystal.h>
#defineLCD_RS7// Register select
#defineLCD_E6// Enable
#defineLCD_D45#defineLCD_D54#defineLCD_D63#defineLCD_D72
bytecc[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
LiquidCrystallcd(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.
voidcreateBarChars(void){
bytemask=0x10;
bytecurrent=0;
for(intcgchar=1;cgchar<=4;cgchar++){
current|=mask;
mask=mask>>1;
for(inti=0;i<8;i++)cc[i]=current;
lcd.createChar(cgchar,cc);
}
for(inti=0;i<8;i++)cc[i]=0x1f;// Create full block.
lcd.createChar(0,cc);
}
voiddrawBar(bytex,bytey,bytepixels){
inti;
byteblocks=pixels/5;// 5 pixels wide per character.
byterem=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);
}
}
voidsetup(){
lcd.begin(16,2);// set up the LCD's columns and rows
lcd.clear();lcd.print("Time:");createBarChars();
}
longcountTime=0;
longoldTime=0;
voidloop(){
staticintidxcg=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.
}
}
A PIR sensor lets your Arduino sense movement without contact. This tutorial covers PIR sensor basics, connecting one to an Arduino board and coding a motion detector.
Arduino Hall Effect Sensor: Add magnetic sensing superpowers to your Arduino projects with an easy-to-use hall effect sensor. With full code and layout...
Get started with an Arduino humidity sensor using the DHT11, which reports both humidity and temperature. Complete guide with full code for using this sensor
Comments
Have your say about what you just read! Leave me a comment in the box below.
Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.