Part

Character LCD, 16x2

Two rows of sixteen characters, HD44780 style, on four data lines.

See every part
  • 16 pins
  • In 3 projects
  • In 5 lessons
Drawn live by the editor's own code, at the size you see it.
At a glance

The Character LCD, 16x2 in brief

What it is, and where it sits on the bench.

The plain 16x2 character LCD is the HD44780 module with all sixteen pins brought out, the version every kit carried before the I2C backpack arrived. VSS and VDD take ground and 5 volts, V0 sets the contrast, A and K light the backlight, and a sketch drives RS, E and four data lines, D4 to D7, with RW tied to ground; the LiquidCrystal example uses pins 12, 11, 5, 4, 3 and 2 on an Uno. Mokxi models the controller as a state machine, so four-bit and eight-bit modes both work, and it keeps the busy time: a write takes 37 microseconds and a clear 1.52 milliseconds, and a byte clocked in sooner is dropped, the bug behind most garbled screens. Contrast follows the glass too. The crystal is driven by VDD minus V0, so a 10k contrast pot at mid travel shows a blank panel and the text only appears in the last fifth of the turn. A panel that has power but never receives the function set shows a row of solid boxes on its first line. Nothing is read back, not even the busy flag.

Family
Displays
Pins
16

A circuit built around it, running and explained: the LCD simulator.

Pins

16 pins

Named as the editor names them, so a wire lands where you expect it.

Pin
What it does
VSS
Ground.
VDD
Supply.
V0
Contrast; near VSS the characters are darkest.
RS
Low for a command, high for a character.
RW
Read/write; tie to ground.
E
Clock, latches on the falling edge.
D0
D1
D2
D3
D4
D5
D6
D7
A
The backlight LED.
K
The backlight LED.
How to use it

How to use a 16x2 LCD with an Arduino, without I2C

Six signal wires: RS to pin 12, E to pin 11 and D4 to D7 to pins 5, 4, 3 and 2. Tie RW to GND, give VDD and the backlight’s A pin 5 V, and VSS and K ground. Create a LiquidCrystal with those six pins, call begin(16, 2) once, then setCursor() and print().

If the glass stays empty, look at V0 first. Tied to GND, as here, the text is fully dark; on a 10k pot it only appears near the ground end of the turn. A row of solid boxes on the top line means power and contrast are fine and begin() never reached the chip.

Part pin
Board pin
VSS
GND
VDD
5 V
V0
GND
RS
Pin 12
RW
GND
E
Pin 11
D4
Pin 5
D5
Pin 4
D6
Pin 3
D7
Pin 2
A
5 V
K
GND
Arduino Uno: TMP36 thermometer on a 16x2 LCDlive0.000 s 0.00x
Click to open it in the editor
This is the simulator itself, running here. Click anything to open it in the editor.
A first 16x2 LCD sketch with LiquidCrystal
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
  lcd.begin(16, 2);
  lcd.print("hello, world!");
}
void loop() {
  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);
}
How it is modeled

What is true about the Character LCD, 16x2, here

In its help article’s own words: what the simulation gets right, and where it stops.

Modeled

At power-on the interface is eight bits wide; a function-set command can switch it to four, after which every byte is two writes on D4 to D7, high nibble first. Both widths work, because the model is the state machine and not a special case for either. Busy is modeled too: a write takes 37 microseconds and a clear takes 1.52 ms, and a byte clocked in while the controller is still busy is dropped, exactly as it is on the bench, the bug behind nearly every "my LCD prints garbage" question. V0 sets the contrast the way the glass does: the crystal is driven by VDD - V0, and nothing shows until that is about 70% of the supply. On 5 V the text is invisible with V0 above about 1.5 V and fully dark below 0.5 V, so a 10 k contrast pot at mid travel shows a blank panel and the text appears in the last fifth of the turn. Left unwired V0 is taken as VSS, the way the cheap modules with a fixed resistor behave. Before any init the controller is in its one-line reset state and the first line shows a row of solid boxes, the second nothing: the bench's sign that the panel has power and contrast but has never been sent the function set begin() sends, so the wiring, the address or the init is wrong. The boxes go when the init selects two lines. A/K light when A is at least two volts above K, and with neither driven the module's own backlight jumper is taken as fitted.

Not modeled

No reads of any kind: the busy flag, the address counter and DDRAM all read back nothing. No 5x10 font mode, no bias, temperature or viewing-angle effects.

The busy times are the datasheet's two typical figures used as exact values: 37 microseconds for a write and 1.52 milliseconds for clear and home. A real HD44780's timing follows whatever its internal oscillator is doing, so those move by tens of percent between parts and with temperature. Nothing checks the E pulse width or the data setup and hold time either, so a driver can clock the bus as fast as it likes and a real module would not keep up.

Dropping a byte that arrives while the controller is busy is this model's choice, made so the fault is visible and repeatable. On a real part the outcome is undefined and more often a corrupted character than a lost one. The backlight is on or off (A at least 2 V above K) with no brightness and no current.

From 16x2 character LCD (HD44780), in full.

Projects

See the Character LCD, 16x2 in a project

3 built-in projects use it. Each opens in the editor, already wired.

Boards

The boards it is shown on

This board has a built-in project with the Character LCD, 16x2 in it.

Libraries

Arduino libraries for the Character LCD, 16x2

Built in, so the sketch compiles with nothing to install. Each page has the calls, the wiring and an example to run.

Wire up the Character LCD, 16x2

Open the editor and push it into the breadboard. It is free, and it runs on your own machine.