I've got a LCM1602C 16x2 liquid crystal display which I'm experimenting on using switches (without a micrcontroller) to understand how it works (I know that it is much more easier with arduino and using the liquidcrystal library).

I was able to send different instructions like display clear, setting address, changing character entry mode and changing cursor and shift direction, I was also able to enter data and show different characters on the display without problems. However I wasn't able to create a custom graphics using CGRAM commands.

In my book it says that first I need to clear the display, then I need to send a set CGRAM command which is anything between 0100 0000 and 0111 1111, then I need to enter the data row by row total of 8 rows. So I did the following:

  1. send clear instruction by setting D7->D0 0000 0001 while RS input is set low, then initiate command by making the transition low-high-low on E enable input.
  2. set the CGRAM command by setting D7->D0 0100 0000, RS low and E low-high-low transition.
  3. send custom graphics rows D7->D0, RS is low and each row is followed by low-hight-low transition on E input:

    • 0000 1110
    • 0001 0001
    • 0001 0001
    • 0001 0001
    • 0000 1110
    • 0000 1010
    • 0000 1110
    • 0000 0100

But it didn't work, all that happened was that the screen was disabled and the cursor got hidden. What am I missing?

  • \$\begingroup\$ Just took a quick peek on google and I'm not sure I found the correct datasheet, but the datasheet I did find says RS should be 1 to write to ram. \$\endgroup\$
    – gregb212
    Apr 9, 2017 at 4:43
  • \$\begingroup\$ You will rapidly get very tired of toggling switches to load your LCD controller. Every test you have to repeat many many operations. The sincere advantage of using a microcontroller instead is that you can program it to do all the steps. Then you can run it as many times as needed to see what happens. If something is not quite right you can tweak the programming then simply run the program again. \$\endgroup\$ Apr 9, 2017 at 5:36
  • \$\begingroup\$ @gregb212 It seems that you're right, after setting the CGRAM address I made RS High and entered the 8 rows pattern, then I checked the first CGRAM address 0x00 and it had the bitmap pattern I created. What I don't understand now is how to I write the bit battern to a specific CGRAM address like hex address 0x43 instead of 0x40 and what do I have to do exactly after I enter the pattern? \$\endgroup\$ Apr 9, 2017 at 22:24

2 Answers 2


There are up to 8 user-defined graphics that can be programmed and stored on the CGRAM memory, CGRAM memory starts at the address 0100 0000 (0x40 HEX or 64 Decimal) and consists of several equally sized 8 byte blocks.

Graphics has a size of exactly 8 bytes each (1 byte = 8 bits) which occupy a single CGRAM block.

enter image description here

The user-defined graphics can be accessed and displayed using the Display addresses 0000 0000 - 0000 0111 (0x00 - 0x07 HEX, 0 - 7 Decimal). Initially they would be garbage when the display powers up. The following is the list of the user-defined graphics display addresses and the corresponding CGRAM addresses (MSB is on the left):

Graphics Number       Display Address        CGRAM Address
------------------    ------------------     ------------------------
1                     0000 0000              0100 0000 -> 0100 0111
2                     0000 0001              0100 1000 -> 0100 1111
3                     0000 0010              0101 0000 -> 0101 0111
4                     0000 0011              0101 1000 -> 0101 1111
5                     0000 0100              0110 0000 -> 0110 0111
6                     0000 0101              0110 1000 -> 0110 1111
7                     0000 0110              0111 0000 -> 0111 0111
8                     0000 0111              0111 1000 -> 0111 1111

If we want to programme the second graphics for example we have to do the following:

  1. We send the set CGRAM address command to set the address at the begging of the second CGRAM block which is 0100 1000 (RS has to be set low (0) like in all commands) followed by a high-to-low transition on E (enable Input).

  2. We enter the 8 data rows corresponding to the bitmap pattern row by row, before we start we make sure RS is set high (1). With each row we set the data inputs D7->D1 and follow it by a high-to-low transition on E, this will store the data in the current address location and move the cursor to the next address on the right.

After storing all data rows we are done, you might want to clear the display after that because the above procedure would change the cursor position (the reset command is 0000 0001).

At this point the second user-defined graphics is programmed and can be displayed using the display address 0000 0001. The following figure illustrate the above procedure:

enter image description here

Notice that the first three bits of each data row are always 0 because there are only 5 pixels in each row. Also note that if we add more rows in the second step the extra data would be stored in the next CGRAM block which is the third graphics in the above example.

  • \$\begingroup\$ Thank you for the thorough explanation I am able now to create custom graphics without problems. \$\endgroup\$ Apr 10, 2017 at 15:45

It is hard to exactly follow what you did but I think you do not quite understand how the custom graphics characters work. They do not display immediately when you load the bit pattern. What you need to do is first load the bit pattern for one of the (typically 8 available) CGRAM slots. Then you need to cause the regular display memory to accept a bit pattern (character code) that corresponds to the loaded bit pattern.

If you filled the whole first line of the LCD with the same special character code the corresponding bit pattern would show at each position of the first line.

Check out my web page for some additional information on using special symbols with an LCD display.

  • \$\begingroup\$ What do I do after I enter the pattern? how do I make the memory accept the bit pattern? \$\endgroup\$ Apr 9, 2017 at 22:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.