Liquid crystal displays (LCD) come in two main types that are of interest to hobby and DIY makers; Character LCD displays and pixel / graphic LCD displays. This intro “How To” will be covering the more popular and less expensive character LCD displays based on the very common Hitachi HD44780 controller.
LCD displays come in many sizes most often named by the number of rows and then the length of the display line. For example a 1x16 LCD display will have one row of sixteen characters and a 4x20 LCD display will have four rows with twenty characters in each.
LCDs can be have backlighting or be reflective (think calculator). In either case the programming that goes into working these displays is the same. LCDs with backlight normally use two pins to provide power to the backlighting.
2x40 character LCD, without backlighting.
1x16 character LCD with backlighting. Note, black text on a bright background.
2x16 character LCD with backlighting. Note, screen is all black, but to display characters the crystals move to allow the backlighting to show through.
Most LCDs that are being made now come with one row of sixteen pins. The first fourteen pins are used to control the display and the last two are for the backlighting (if the display has backlighting).
Older LCDs sometimes came with two rows of seven making a fourteen pin connector. These fourteen pins, most often, have the same signals on them that the 1x16 pin displays do. For example, pin #1 on the 2x7 connector is the same signal as pin #1 on the 1x16 connector, they are just arranged differently. If you have a 2x7 pin display but need to connect it to a 1x14 (1x16) backpack or device, the basic Message Pump PCB makes a great converter.
Note how the numbering goes 1-2, 3-4 etc up to 13-14 on the top row.
These pins are numbers from 1 to 16 with 1 being closest to edge.
2 Positive 5 volt
3 VEE (Connect to +5 and GND through 10k Pot for display contrast)
4 RS (Low for command - high for characters)
5 RW (Low for write - high for read)
6 E (Toggle to load data and command)
7-14 Data pins
15 Backlight +
16 Backlight Ground
Typical pinout on a Hitachi compatible display with 1x16 pin connector.
There are two types of data that you can send to the LCD.
1. Character data (letters and numbers)
The controller on the LCD interprets the data as a command if the RS pin is low (0) and as Character data when RS is high (1).
The basic process of sending data to the display goes like this;
1. The data pins are set (high) or cleared (low) with the data that you would like to load into the display.
2. RS is set for character data or cleared for a command.
3. RW is cleared (0) to write data to the LCD or set (1) to read data from the LCD
4. E is toggled, first set high then low. This loads the data, RW and RS into the LCD.
LCDs based on the Hitachi HD44780 controller must be initialized after they are powered-up. The reason that the LCDs must be initialized is because there are a few critical options that the display must “know” before it can work or communicated properly.
The most import of which is wether to use an eight or four bit data interface. Hitachi and compatible LCDs can be set to use either 8 or 4 of the data pins to communicate with the host controller that is driving it. Using a four pin data bus lets you save on pins, but your controller must divide each instruction into two four bit segments and then send them one at a time to the display. So the trade off is less pins versus more programming and slower communication. (The reduced speed of having to send data twice has little effect on the display, but it does busy your processor for a longer amount of time.)
Other initialization options include font size (only some displays), shift to right or left, blinking, one or more lines, etc.
8 bit initialization steps from Hitachi’s HD44780U Spec sheet.
Part of the LCD initialization steps from the I2CClockTalk Arduino sketch found on the VoiceShield pages.
Note the similarities with the Hitachi initialization.
Ok, so you initialized your new 1x16 display and cleared it so that the cursor is at the first character position. Now you start sending your “Hello World” message to the screen.
Great success ! ..... but wait
The letters start appearing on the display “H” “He” “Hel” “Hell” “Hello” “Hello W” “Hello Wo” “Hello Wo” “Hello Wo” ...
Ah, what’s wrong ?
You check your coding, but it looks right. Why are the last three letters not showing?
To complicate matters the display memory locations of an LCD are not all sequential the way you would think that they should be.
When you send the LCD a character to display, you are not actually sending it to the screen part of the display, but rather a memory location that the display uses to know what to display on the screen. The problem here is that the memory location and the mapping to positions on the screen are not always sequential.
The “Hello World” example above is often what gives people trouble using a 1x16 LCD for the first time. Here the “r” “l” “d” went into memory address 0x88,0x89 and 0x8A which are not visible on this display !
Hexadecimal memory locations of a 1x16 LCD:
Note that from the eight to the ninth character position the memory jumps. So, to finish displaying “Hello World” the controller would have to jump to memory location 0xC0 (at the red arrow) to continue displaying “rld”.
The solution to this problem is easy to deal with.
Solution: When you are ready to display a character in the ninth position on a 1x16 display you simply send the memory address to the display, but as a command.
For 1x16 and all the display larger then this, the memory mapping of the DDRAM (Display RAM) is not in the same range as the other commands, such as “clear display”, “home display” etc... so there is no problem sending the memory address as a command.
Here is a short list of popular display sizes and the memory mapping that we have found in them. Note: not all displays will necessarily have the same mapping, even when they are the same size. Use this a “Quick Start” reference when working on your own.
Examples of LCD Display RAM (DDRAM) Hexadecimal Memory mapping
When it is actually time to use an LCD you have a few choices of how to do it. You can connect it directly to your Arduino or micro-controller (MCU) and use a lot of pins and wires or your could use a backpack.
1. Connect it directly to you micro-controller, building your own software and interface.
2. Use a back-pack.
Using a backpack has a few advantages over connecting the LCD directly to your micro-processor. Besides using less wires, (and pins) some backpacks take over the entire job of driving the display. All your code has to do is send the text out of the appropriate interface, I2C, serial, SPI etc ... This can save your micro-controller a lot of memory, and processor time. And, it also lets you get your projects working sooner, since you do not have to code and debug software to drive the display on top of the rest of your project.
A. Backpacks that do all the work, these free your MCU (and you) to do other tasks and when ready to display a message you simply send data to the backpack.
B. Backpacks that reduce the pin-out burden on your MCU. With this type of backpack, your MCU still initializes and drives the LCD, but through an interface with fewer wires.
Comparison of some LCD backpacks:
Eg. 1. With the I2C LCD Interface your micro-controller must initialize and drive the LCD.
Eg. 2. With the Message Pump Serial, the backpack does all the work, your micro-controller just sends it either I2C or TTL level serial data.
* As of Firmware v2 , all Message Pump backpacks have I2C enabled.
Most displays work with the standard 128 ASCII characters. Often times, the displays are also able to display other characters, these include Asian characters and other special symbols and icons.
Sending text to the display is very straight forward, you simply send the ACSII text and it will display.
Numbers can be more difficult !
Your micro-controller measures a sensor and returns the value of five. You send the value to the display and you either get nothing or a strange looking character.
The value of five and the character “5” are two different things. The ASCII number for the character “5” is 53 !
Add 48 to any number that you are sending to the display.
But, you can only send a single digit at a time to the display. So if you have the value of 139 to display, first it must be chopped into “1”, “3”, and “9” then you must add 48 to each before sending them to the display to convert the value into ASCII.
Copyright SpikenzieLabs 2019