The common LCD displays using an Hitachi HD44780 controller have the ability to have 8 user defined lcd characters displayed.

These characters have a matrix of 5 x 8 which you can define at will. Using this it is posible to display user defined characters.
Examples of such characters are shown below. These characters can be static such as the hart or musical note example or be made to animate by showing two images one after another.
This is how the pacman symbols are meant to be used.

For the large character display the following custom characters were generated. You also need a blank and a character with all fields black. These were not generated but rather character 020 and 255 were used.
This allowed two more characters to be generated which could make a bar chart complete.
These custom characters needed to be combined to form the actual display.
For the number zero as an example 255 0 255 and second row 255 1 255.
The LCD4bit driver has now got the ability to pass pin numbers through a constructor and also can use any pin numbers. Also support for a 4 row display was added. Thank you nuelectronics for sharing your library.

The following font allows you to create the all numbers and a dot with just four characters allowing the other 4 characters to be used for something else.
The characters space and 255 are use to display a blank and full segment respectively. This is used in all the fonts defined here.



If you want a slightly more attractive font and are prepared to use 6 characters you can use this definition.





You can make a progress bar with the following four characters plus the space and 255 character.
This is why using only four characters for the numbers can make sense as you can then have the numbers plus this vertical bargraph at the same time.

I used an excel spreadsheet to design the characters. This you can download here.




You can also make animated chracters if you replace a character at a certain location in rapid succession.
One example of a useful animation is the hourglass  cursor to let users know that the program is busy.
This simple animated icon works much better than a message somewhere on the screen that says, “please wait, the program is busy…”.
For instance an hourglass character can be made to empty over time and then repeat.
Other examples are the vertical bargraph and battery charging display.






Here a library that helps to display user defined characters on an LCD.

Here is a very clever someone who has managed to make a oscilloscope using a LCD display. This is done by changing the  custom characters on the fly.
I must have a go at doing that with my serial LCD one day.

Here is an LCD character generator with which you can construct custom characters. Below you can see a screen shot.

The website from which you are supposed to download the software is no longer existing so i included a local copy.
There is also another page here where you can do this online without downloading a program.



Pin assignment

The pin assignment shown in Table 1. is the industry standard for character LCD-modules with a maximum of 80 characters.
I have never seen anything different but you should of course check the datasheet.


Table 1., Pin assignment for <= 80 character displays
Pin number Symbol Level I/O Function
1 Vss Power supply (GND)
2 Vcc Power supply (+5V)
3 Vee Contrast adjust
4 RS 0/1 I 0 = Instruction input
1 = Data input
5 R/W 0/1 I 0 = Write to LCD module
1 = Read from LCD module
6 E 1, 1–>0 I Enable signal
7 DB0 0/1 I/O Data bus line 0 (LSB)
8 DB1 0/1 I/O Data bus line 1
9 DB2 0/1 I/O Data bus line 2
10 DB3 0/1 I/O Data bus line 3
11 DB4 0/1 I/O Data bus line 4
12 DB5 0/1 I/O Data bus line 5
13 DB6 0/1 I/O Data bus line 6
14 DB7 0/1 I/O Data bus line 7 (MSB)
15 LED + LED +
16 LED – LED –

Instruction set

Table 2. HD44780 instruction set
Instruction Code Description Execution time**
Clear display 0 0 0 0 0 0 0 0 0 1 Clears display and returns cursor to the home position (address 0). 1.64mS
Cursor home 0 0 0 0 0 0 0 0 1 * Returns cursor to home position (address 0). Also returns display being shifted to the original position. DDRAM contents remains unchanged. 1.64mS
Entry mode set 0 0 0 0 0 0 0 1 I/D S Sets cursor move direction (I/D), specifies to shift the display (S). These operations are performed during data read/write. 40uS
Display On/Off control 0 0 0 0 0 0 1 D C B Sets On/Off of all display (D), cursor On/Off (C) and blink of cursor position character (B). 40uS
Cursor/display shift 0 0 0 0 0 1 S/C R/L * * Sets cursor-move or display-shift (S/C), shift direction (R/L). DDRAM contents remains unchanged. 40uS
Function set 0 0 0 0 1 DL N F * * Sets interface data length (DL), number of display line (N) and character font(F). 40uS
Set CGRAM address 0 0 0 1 CGRAM address Sets the CGRAM address. CGRAM data is sent and received after this setting. 40uS
Set DDRAM address 0 0 1 DDRAM address Sets the DDRAM address. DDRAM data is sent and received after this setting. 40uS
Read busy-flag and address counter 0 1 BF CGRAM / DDRAM address Reads Busy-flag (BF) indicating internal operation is being performed and reads CGRAM or DDRAM address counter contents (depending on previous instruction). 0uS
Write to CGRAM or DDRAM 1 0 write data Writes data to CGRAM or DDRAM. 40uS
Read from CGRAM or DDRAM 1 1 read data Reads data from CGRAM or DDRAM. 40uS

– DDRAM = Display Data RAM.
– CGRAM = Character Generator RAM.
– DDRAM address corresponds to cursor position.
– * = Don’t care.
– ** = Based on Fosc = 250KHz.

Table 3. Bit names
Bit name Settings
I/D 0 = Decrement cursor position 1 = Increment cursor position
S 0 = No display shift 1 = Display shift
D 0 = Display off 1 = Display on
C 0 = Cursor off 1 = Cursor on
B 0 = Cursor blink off 1 = Cursor blink on
S/C 0 = Move cursor 1 = Shift display
R/L 0 = Shift left 1 = Shift right
DL 0 = 4-bit interface 1 = 8-bit interface
N 0 = 1/8 or 1/11 Duty (1 line) 1 = 1/16 Duty (2 lines)
F 0 = 5×7 dots 1 = 5×10 dots
BF 0 = Can accept instruction 1 = Internal operation in progress

Writing data to the LCD is done in several steps

Set R/W bit to low
Set RS bit to logic 0 or 1 (instruction or character)
Set data to data lines (if it is writing)
Set E line to high
Set E line to low
Read data from data lines (if it is reading)

Reading data from the LCD is done in the same way, but control line R/W has to be high. When we send a high to the LCD, it will reset and wait for instructions. Typical instructions sent to LCD display after a reset are: turning on a display, turning on a cursor and writing characters from left to right. When the LCD is initialized, it is ready to continue receiving data or instructions. If it receives a character, it will write it on the display and move the cursor one space to the right. The Cursor marks the next location where a character will be written. When we want to write a string of characters, first we need to set up the starting address, and then send one character at a time. Characters that can be shown on the display are stored in data display (DD) RAM. The size of DDRAM is 80 bytes.

The LCD display also possesses 64 bytes of Character-Generator (CG) RAM. This memory is used for characters defined by the user. Data in CG RAM is represented as an 8-bit character bit-map. Each character takes up 8 bytes of CG RAM, so the total number of characters, which the user can define is eight. In order to read in the character bit-map to the LCD display, we must first set the CG RAM address to starting point (usually 0), and then write data to the display. The definition of a ‘special’ character is given in the picture.

Before we access DD RAM after defining a special character, the program must set the DD RAM address. Writing and reading data from any LCD memory is done from the last address which was set up using set-address instruction. Once the address of DD RAM is set, a new written character will be displayed at the appropriate place on the screen. Until now we discussed the operation of writing and reading to an LCD as if it were an ordinary memory. But this is not so. The LCD controller needs 40 to 120 microseconds (uS) for writing and reading. Other operations can take up to 5 mS. During that time, the microcontroller can not access the LCD, so a program needs to know when the LCD is busy. We can solve this in two ways
One way is to check the BUSY bit found on data line D7. This is not the best method because LCD’s can get stuck, and program will then stay forever in a loop checking the BUSY bit. The other way is to introduce a delay in the program. The delay has to be long enough for the LCD to finish the operation in process. Instructions for writing to and reading from an LCD memory are shown in the previous table.


Leave a Comment