Overview
Display modules are very usefully addition to any microcomputer system. Constant evolution of the display technology has led to explosion of choices from classical passive 2 color LCD displays to the glowing OLED (Organic Light Emitting Diode) or VFD (Vacuum Fluorescent Display) modules. Despite all of the changes in the underlaying display technology it is almost certain that character module is based on the industry standard controller the Hitachi (now Renesas) HD44780 or one of its clones and variations.
This tutorial describes step by step development of the HBBR Basic software library used to interface an HD44780 based module to the ARM based microcontroller.. Greatest focus is on a the details of the software written in HBBR Basic but the description should be useful to anybody working with the HD44780 based modules.
For anybody seeking further information there are number of excellent web based resources, some them are mentioned in the links section.

HD44780 Controller
First step when working with the display module is to verify that it indeed is based on either one of the variants or a clone. On the chip side of the module look for a chip labeled with one of the variations listed below ( * character represents rest of the characters):
HD447800, HD44780A*, HD44780F*, HD44780R*, HD44780S*,HD44780U*
If none of the above can be found it could be one of the HD44780 clones listed below:
SED1278 Epson, KS0066 Samsung, ST7066 Sitronix or SPLC780A1 Sunplus
Once the positive identification of the controller has been made the next step is to determined how the module is arranged. The HD44780 has internal memory for up to 80 characters to be displayed, and a single chip modules are typically arranged as:
8x1,8x2, 10x1, 12x2, 16x1,16x216x4, 20x1,20x2,20x4, 24x2, 40x1, 40x2, 80x1
There are also dual chip modules in existence that support up to 160 characters, they are typically configured as:
20x8, 40x4, 80x2
The basic information on the HD44780 can be found in the datasheet. Probably the easiest one to find is the datasheet for the HD44780U ( aka LCD-II) variant. Here is the local link to it : [Insert URL here]
Hardware considerations
The easiest route to work with the display modules is to use a microcontroller board that comes with the module either built in or is designed to interface with one.
Required Voltage
Important consideration when interfacing to the ARM based microcontroller is the logic power supply voltage required by the display module. Most common value for the LCD module is 5 V (can operate on 4.5 V) while typical ARM based microcontrollers operate on 3.3V or lower. However, microcontrollers are designed to work with a 5 V IO signals, so as long as the module can be powered with correct voltage it can be used directly with ARM based microcontroller. Newer variants of the HD44780 support lower power operation with the power supply voltage between 2.5 and 5V. The easiest LCD modules to work with are the ones with LED back light requiring only single 5 V power supply. Some older modules require high voltages for backligthing and should be AVOIDED.
NOTE:
Always consult your LCD module documentation before connecting the module to your board.
Connector
Display modules come with 14 pin interfaces arranged either as 1x14 or 2x7, but no matter what the layout is the pin assignment is the same. Some modules have 2 extra pins 15 and 16 for backlight power.
Pin assignment table for 14 pin interface.
NOTE:
Always verify pin assignment before connecting the module.
Pin | Description |
| Notes |
1 | VSS | GND | Ground |
2 | VCC | +5 V | Logic power supply |
3 | VEE | Contrast control | Connect to a voltage between GND and VCC – see documentation for details |
4 | RS | Registers Select |
|
5 | R/W | Read / Write |
|
6 | E | Enable |
|
7 | DB0 | Bit 0 | Connect to GND if not used |
8 | DB1 | Bit 1 | Connect to GND if not used. |
9 | DB2 | Bit 2 | Connect to GND if not used. |
10 | DB3 | Bit 3 | Connect to GND if not used. |
11 | DB4/PD0 | Bit 4 / Bit 0 |
|
12 | DB5/PD1 | Bit 5 / Bit 1 |
|
13 | DB6/PD2 | Bit 6 / Bit 2 |
|
14 | DB7/PD3 | Bit 7 / Bit 3 / BF |
|
Controlling HD44780
HD44780 has built-in 2 registers IR Instruction Register and DR Data Register through which software can control operation of the display.
From the hardware perspective HD44780 was designed to be directly interfaced with number of different MPU through a well defined bus. This bus is used to transfer data between MPU and display controller. It is a bidirectional parallel bus that can operate in 2 modes full size 8 bit or half size 4 bit. There are 3 control signals RS, R/W and E and either 8 data bits DB0-DB7 or 4 PD0-PD3, DB7 (PD3) is reused as a Busy Flag indicator.
In addition to defining signals bus specification has to describe all of the possible operations that can be performed using the bus with detailed sequencing of the signals as well as precise timing information. Although the HD44780 is designed to be directly interfaced with the MPU it is unlikely to find ARM based microcontroller with the external bus interface compatible with HD44780. But direct bit manipulation (bitbanging) technique makes it possible to emulate bus behavior under software control, while relaxed timing requirements make it fairly easy to meet them.
In the case of HD44780 RS and R/W control signals are used to determine transfer type and direction while E is used to sequence bus operation. RS can be thought of as a 1 bit address, it selects between Instruction.
HD44780 bus transfers
RS | R/W | Operation |
0 | 0 | IR (Instruction Register) write |
0 | 1 | Read busy flag DB7 and address counter DB0 to DB6 |
1 | 0 | DR (Data Register) write |
1 | 1 | DR (Data Register) read |
4 Bit mode signal direction
Pin | Direction | Comment |
E | O | Output only |
RS | O | Output only |
R/W | O | Output only |
PD0 | IO | Input/Output |
PD1 | IO | Input/Output |
PD2 | IO | Input/Output |
PD3/BF | IO | Input/Output |
The Wikipedia link explaining in more details of the bus
Selecting control pins
If the microcontroller board does not have a built-in interface for the display module it is possible to select almost any available pin for the interface. The only limitation is on the data pins which must be able to operate as both input or output, control signals can be output only.

In HBBR Basic the easiest way to control the pins is using GPIO Hardware Abstraction Class. It allows full control over the pin using set of operations. All pins and their functions are identified through integer constants.
GPIO functions used are:
Configure for pin function and direction
Clr to set pin output to 0
Set to set pin output to 1
Pin to input pin state
Function GPIO.Configure(ByVal pin As Integer) As Integer
Function GPIO.Clr(ByVal pin As Integer)
Function GPIO.Set(ByVal pin As Integer)
First step is to identify and assign pins to the interface. Below is an example of pin configuration for a Hobby-Robtotics iH1 board supporting lpc2148 or lpc2138.
' Pin assigment for iH1_lpc2138 series board
' Customize for specific board!
' RS - P1.23
' R/W - P1.25
' E - P1.22
' PD0 - P1.27
' PD1 - P1.20
' PD2 - P1.26
' PD3 – P1.21
The actual assignment is done in lcd_initialize_LCD_pin_iH1_lpc2138 sub called from Main.
For the control pins two values are defined, one for setting pin to the output LCD_X_OUT and the other for setting pin value LCD_X as in the example below:
LCD_E = P1_22
LCD_E_OUT = P1_22_OUT
Data pins require 3 values, the extra one for setting pin to be input LCD_PDX_IN as in the example below:
LCD_PD0 = P1_27
LCD_PD0_OUT = P1_27_OUT
LCD_PD0_IN = P1_27_IN
Testing pin assignment
Before connecting display to the ARM microcontroller it is highly recommended to test the actual pin assignment. The test is located in the lcd_test Sub which is called when LCD_TEST is defined. The test procedure is using Debug.Break statement to stop the program execution and allow for manual inspection of the state of the pins.
First test sets all of the pins to LOW and then step by step sets pins to HIGH state, stopping after each pin. At the end of the testing data pins are turned to input while all 3 control pins are pulsed in infinite loop.
After successful test and verification of connection display module can be safely connected to the ARM board.
Write to Instruction Register
Fundamental in controlling HD44780 is the ability to send instructions to it. This requires implementing a bus cycle emulation through bitbanging as done in in lcd_write_IR subroutine.
For a 4 bit interface bus cycle consists of 4 steps:
1 set the control lines
2 output high nibble
3 output low nibble
4 Either synchronize using Busy Flag or wait fixed 10 ms delay for the end of the controller operation.

Setting control lines is straightforward using GPIO functions Clr and Set
' RS=0 R/W=0 E=0
res = IO.Clr(LCD_RS)
res = IO.Clr(LCD_RW)
res = IO.Clr(LCD_E)
Outputing high nibble and low nibble works very similar with the only difference being the bits used for output. The operation is done in lcd_output_high_nibble and lcd_output_low_nibble subroutines. Both of which take as an argument byte to be outputted.
The sequence is as follows:
E pin is raised high with:
res = IO.Set(LCD_E)Call to lcd_set_data_pins_OUT ensures that data pins are configured as outputs.
4 data pins are then set to the value corresponding to the bit position in the byte
1 ms delay is initiated
E pin is set low with:
res = IO.Clr(LCD_E)1 ms delay is initiated
Call to lcd_set_data_pins_IN reverts data pins to be configured as inputs
In 4 bit bus mode for each byte two nibbles have to be outputted by calling lcd_output_high_nibble and lcd_output_low_nibble subroutines, order is important!
After receiving instruction or data HD44780 controller takes some time to process it. Last step in write to the Instruction Register makes ensures that controller is ready for the next operation. This step can be implemented in 2 ways;
Wait fixed delay (longer then any possible processing delay) before returning control to the program
Use Busy Flag to determine end of the processing
Both approaches have their advantages.
Using fixed delays is simple to implement and avoids a situation where program is stuck in the infinite loop waiting for the busy flag to clear.
Using Busy Flag has the advantages of speeding up entire process of sending instructions and data by avoiding unnecessary delays. However, there is a possibility that program can become stuck waiting for Busy Flag. This situation can be dealt with timeouts but it complicates code.
Initializing after power-up
After power has been applied controller has to be initialized to enable 4 bit bus size. Initialization is achieved by following steps outlined in data sheet “Initializing by Instruction”. All these steps are implemented in lcd_initialize_HD44780 and in lcd_init_4_bit_interface subroutines.
The steps are as follows:
Wait for a fixed delay at least 15 ms after power has been applied ( 500 ms )
Set RS=0 R/W=0 E=0 to low
Output &h3 nibble 3 times with 10 ms delay between the steps
Output &h2 nibble
Set mode using Function set instruction, the exact mode value has to be determined for a specific display.
At this point bus interface is initialized to the required 4 bit and controller is ready to accept instruction over the 4 bit bus. To finish initialization code in lcd_initialize_HD44780, following instructions are sent.
' Display ON/OFF
Call lcd_write_IR(LCD_DISP_ALL_ON_CMD)
' Display Clear
Call lcd_write_IR(LCD_CLEAR_CMD)
' Entry Mode Set
'Increment and shift cursor
Call lcd_write_IR(&H06)
Sending Instructions
High level subroutine lcd_write_IR is used to send instructions to the HD44780 controller. As an argument it takes byte with instruction code. There are a number of predefined constants with instruction codes,
High level functions
lcd_write_string
This subroutine is used to send the a string of the characters to the display module the current cursor position.
lcd_set_cursor_pos(row,col)
This subroutine is used to set current cursor position.
Example
The example application first initializes display then sends “Hello World!” string. After that it enters infinite loop reading a line and sending displaying it on the sencond line.
References
HITACHI HD44780U (LCD-II) (Dot Matrix Liquid Crystal Display Controller/Driver) ADE-207-272(Z) '99.9 Rev. 0.0 - datasheet.
Links
Peter Ouwehand -How to control a HD44780-based Character-LCD
Ian Harries - HD44780-Based LCD Modules http://www.doc.ic.ac.uk/~ih/doc/lcd/
Mark Owen's site with graphical design characters (can be slow to load!) HD44780 LCD User-Defined Graphics
LCD Technology http://en.wikipedia.org/wiki/Liquid_crystal_display
OLED http://en.wikipedia.org/wiki/Organic_light-emitting_diode
VFD http://en.wikipedia.org/wiki/Vacuum_fluorescent_display





