[M8CU]-[Nuvoton] Interface with I2C LCD
If you’ve ever tried connecting an LCD display, you’ve probably noticed it requires quite a few pins. Even when using 4-bit mode, you still need seven/six connections – which takes up about a lot of available digital I/O pins.
A better solution is to use an I2C LCD display. It only needs two pins that aren’t even part of the regular digital I/O pin set. Even better, these pins can be shared with other I2C devices. This makes your wiring much simpler and saves those valuable pins for connecting other sensors or components in your projects.
Hardware Overview
A typical I2C LCD display consists of two main parts: an HD44780-based character LCD display and an I2C LCD adapter. Let’s explore both of these components in more detail.
Character LCD Display
Character LCDs are specially designed to display letters, numbers, and symbols. A 16×2 character LCD, for example, can show 16 characters across each line, with two lines total.
If you look very closely at the screen, you’ll notice small rectangular boxes for each character position. Inside each of these rectangles is a grid of 5×8 tiny dots or pixels. These pixels light up in different patterns to form different letters, numbers, or symbols.
I2C LCD Adapter
The key component of this adapter is an 8-bit I/O expander chip called PCF8574. This clever chip converts the I2C data from your MCU into the parallel data that the LCD display needs to function.

The adapter board also includes a small trimpot that lets you make fine adjustments to the display’s contrast.

You’ll notice there’s a jumper on the board that supplies power to the backlight. If you want to control how bright the backlight is, you can simply remove this jumper and connect an external voltage source to the header pin marked ‘LED’.
I2C Address of LCD
If you have multiple devices on the same I2C bus, you may need to set a different I2C address for the LCD adapter to avoid conflicts with other I2C devices.
For this purpose, the adapter comes with three solder jumpers/pads (labeled A0, A1, and A2). For a single LCD, you can leave these untouched; however, if you connect multiple I2C devices or LCDs, you’ll need to make sure each has a unique address by modifying these jumpers. You can change the address by shorting a jumper with a small blob of solder.

An important thing to know is that different companies, like Texas Instruments and NXP Semiconductors, make the same PCF8574 chip. The I2C address of your LCD depends on which company manufactured the chip.
If your LCD has Texas Instruments’ PCF8574 chip:
According to Texas Instruments’ datasheet, the three address selection bits (A0, A1, and A2) are located at the end of the 7-bit I2C address register.

Since there are three address inputs that can be either HIGH or LOW, there are eight possible combinations (2^3 = 8) of addresses.
All three address inputs are pulled HIGH by default using onboard pullup resistors. This gives the PCF8574 a default I2C address of 0x27.
When you short a solder jumper, you pull that address input LOW. If you were to short all three jumpers, the address would change to 0x20. So the range of possible addresses goes from 0x20 to 0x27.
You can set different I2C addresses according to this table:

If your LCD has NXP’s PCF8574 chip:
According to NXP Semiconductors’ datasheet, the three address selection bits (A0, A1, and A2) are also located at the end of the 7-bit I2C address register. However, the remaining bits in the address register are different from the Texas Instruments chip.

Just like with the Texas Instruments chip, there are eight possible address combinations since the three inputs can be either HIGH or LOW.
All three address inputs are pulled HIGH by default using onboard pullup resistors. This gives the PCF8574 a default I2C address of 0x3F.
When you short a solder jumper, you pull that address input LOW. If you were to short all three jumpers, the address would change to 0x38. So the range of possible addresses goes from 0x38 to 0x3F.
You can set different I2C addresses according to this table:

So the I2C address of your LCD is most likely 0x27 or 0x3F. If you’re not sure what your LCD’s I2C address is, don’t worry! There’s an easy way to figure it out, which you’ll learn about later in this tutorial.
I2C LCD Display Pinout
The I2C LCD Display has only four pins. The following is the pinout:
VCC is the power supply pin. Connect it to the external 5V power supply.
SDA is the I2C data pin.
SCL is the I2C clock pin.
Wiring an I2C LCD Display to an N76E/MS51
Connecting an I2C LCD is much simpler than connecting a standard LCD. You only need to connect four pins instead of many more.
- First, connect the VCC pin to the 5V output and the GND pin to the ground.
- Next, we need to connect the pins used for I2C communication.
- The table below shows you all the pin connections you need to make:
I2C LCD | N76E/MS51 | |
VCC | 5V | |
GND | GND | |
SCL | SCL (P1.3) | |
SDA | SDA (P1.4) |
Adjusting The LCD Contrast
After you finish wiring the LCD to your MCU, you’ll need to adjust the contrast of the LCD display. Look for a small blue trimpot on the I2C adapter board – this controls the LCD’s contrast.
Now, power up your board. You should see the backlight glow up right away. Take a small screwdriver and gently turn the potentiometer knob. As you adjust it, you’ll start to see the first row of rectangles appear on the screen. These rectangles are where characters will show up. If you can see those rectangles clearly, congratulations—your LCD is working perfectly and is ready for you to display text!
Determining the I2C Address
Before we jump into the example code, you’ll need to know your LCD’s I2C address so you can properly communicate with it. As we mentioned earlier, your LCD’s I2C address is probably either 0x27 or 0x3F. You might find this address printed on a sticker that came with your LCD or listed in the product information. But don’t worry if you can’t find this information anywhere! There’s an easy solution – you can run a simple I2C scanner sketch that will help you discover the correct address automatically. Here’s how:
You can find this sketch in lib\N76_i2c\examples\I2C_scanDevice.c
After uploading the sketch to your MCU, open the serial monitor and set it to 115200 baud. In a few moments, you should see the I2C address of your LCD display appear on the screen.
Be sure to write down this address somewhere safe. You’ll need it when we work with the LCD in later examples.
Basic Sketch – Hello World
With the hardware connected and the library, we can write a simple sketch to display text on the LCD. In this example, we’ll blink Hello world! in first line and N76E003 I2C LCD in second line.
Before you upload the sketch, you need to make two important changes to make it work with your specific LCD. You must enter the correct I2C address of your LCD (which we found earlier) and specify the display dimensions in the LCDI2C_begin()
. If you’re using a 16×2 character LCD, enter 16 and 2; if you’re using a 20×4 character LCD, enter 20 and 4.
Once you’ve made these changes, you’re ready to try the complete sketch:
After uploading this code to your MCU, this is what you should see on the screen:
Create and Display Custom Characters
Sometimes you may want to display special characters that aren’t part of the standard alphabet or numbers – for example, symbols like a smiley face, a degree symbol (°) for temperature readings, or fun icons like hearts, music notes, or arrows.
The good news is that HD44780 LCDs allow you to create up to 8 custom characters of your own design! As we learned earlier in this tutorial, each character on the LCD is displayed using a small grid of pixels arranged in a 5×8 pattern (5 pixels wide by 8 pixels tall). To create your own character, you’ll need to decide which of these tiny dots should be turned on and which should be off.
To create your custom character, you first need to make an 8-byte array in your code. Each byte in this array represents one horizontal row in your character, starting from the top row and going down to the bottom row. For each byte, you’ll use the bits (the 1s and 0s in binary) to indicate which pixels should be ON (1) and which should be OFF (0). Only the first 5 bits of each byte are used since the character is 5 pixels wide.
Once you’ve designed your character by setting up this array, you can use the createChar()
function to store your custom character into the LCD’s CGRAM (Character Generator RAM), which is a special memory area designed just for holding custom characters.
Now, let’s go ahead and create some cool custom characters for your projects!
CGROM vs. CGRAM
All Hitachi HD44780 driver-based LCDs have two types of memory: CGROM (Character Generator Read-Only Memory) and CGRAM (Character Generator Random Access Memory).
CGROM is non-volatile memory, which means it keeps its data even when power is turned off. It stores predefined dot patterns for standard ASCII characters, such as letters, numbers, and common symbols. When you want to display an “A” on the screen, you send the code for “A” (which is 0x41 in hexadecimal), and the LCD controller looks up the dot pattern for “A” in its CGROM and displays it. This makes showing regular characters super quick and easy!
CGRAM, however, is volatile memory, so it loses its data when power is removed. This memory is flexible and lets you store custom dot patterns that aren’t part of the built-in set. For instance, you can design your own symbols, icons, or unique characters for your project. However, CGRAM has limited space – only 64 bytes total. On a standard 5×8 pixel LCD, this means you can only store 8 custom characters (since each character needs 8 bytes). If you’re using a 5×10 pixel LCD, you can only store 4 custom characters because each one needs more memory.
In summary, CGROM is read-only with fixed character patterns that can’t be changed, while CGRAM is writable, allowing you to create and save custom characters whenever you need them.
Custom Character Generator
Creating custom characters has never been easier! We’ve developed a helpful tool called the Custom Character Generator. See the blue grid below? You can click on any pixel to turn it on or off, and as you do this, the code for your character is automatically created right next to the grid. You can copy this code directly into your sketch.

byte Character[8] = |
{ |
0b00000, 0b00000, 0b01010, 0b11111, 0b11111, 0b01110, 0b00100, 0b00000 |
}; |

The possibilities for what you can create are almost endless! You could make arrows, simple animals, game characters, weather symbols, or any small icon you can fit in the 5×8 grid. The only limitation is that the library only lets you use eight custom characters at one time. But don’t worry – eight different custom characters are still plenty to make your project unique and interesting!
Example Code
The sketch below shows you exactly how to display your custom characters on the LCD:
When you upload this code to your MCU, your LCD will display something like this:
No comments