STM32 I2C LCD Library & Examples (16×2, 20×4, Multiple LCDs)

This is a comprehensive guide for STM32 I2C LCD Interfacing (I2C LCD 16×2, 20×4, and Multiple I2C LCDs). You’ll learn how to use our STM32 I2C LCD Library and create some example projects to practice what we’ll be learning in this tutorial. We’ll implement the following examples in this tutorial:

  • STM32 I2C LCD 16×2 Text Display
  • STM32 I2C LCD 16×2 Scrolling Text Display
  • STM32 I2C LCD 16×2 Custom Characters Display
  • Multiple I2C LCD Displays Interfacing With STM32
  • STM32 I2C LCD 20×4 Display Interfacing

We’ll start off by explaining how the I2C LCD module works, its pinout, and how to connect it to your STM32 board. We’ll display some text on the I2C LCD screen, make the text scroll on the LCD, and also create some custom characters and emojis. Without further ado, let’s get right into it!

Table of Contents

  1. STM32 I2C LCD
  2. STM32 I2C LCD Interfacing
  3. STM32 I2C LCD Library (Driver)
  4. STM32 I2C LCD Library Integration
  5. STM32 I2C LCD 16×2 Example
  6. STM32 I2C LCD 16×2 Example Code [Project]
  7. STM32 Multiple I2C LCD Example Code [Project]
  8. STM32 I2C LCD Common Issues Troubleshooting
  9. Wrap Up


LCD (Liquid Crystal Display) is typically used in embedded systems to display text and numbers for the end user as an output device. The 16×2 alphanumeric display is based on the Hitachi HD44780 driver IC. Which is the small black circular chip on the back of the LCD module itself. This is the controller that controls the LCD unit and we communicate with using an STM32 microcontroller to send commands and text messages.

Alphanumeric LCD 16×2

The LCD module consists of 16×2 character cells (2 rows x 16 columns), each cell of which is 5×8 dots. Controlling all of these individual dots is a tedious task for our STM32 microcontroller. However, it doesn’t have to do so. As there is a specific function controller on the LCD itself controlling the display while reading the user’s commands & data (the Hitachi HD44780 controller).


The tutorial linked below is highly recommended to learn more about STM32 LCD interfacing with GPIO-based Library, it’s bare metal and very informative.

STM32 LCD 16x2 Library & Example Driver (Interfacing LCD Display)

This article will provide you with more in-depth information about STM32 LCD 16×2 interfacing, how LCDs work, how to use the GPIO-based LCD16X2 library and integrate it into your projects, and more. It’s highly recommended!

I2C LCD Module (PCF8574 IO Expander)

The I2C IO expander IC (PCF8574) is commonly used as a cheap solution to implement an I2C LCD interface that replaces the classic parallel connection to the LCDs (at least 6 pins) with an easy-to-use I2C bus (only 2 pins). Using it saves a lot of the STM32 microcontroller’s IO pins that would have been consumed to create a generic LCD parallel communication.

PCF8574 I2C LCD IO Expander With PIC Interfacing Tutorial

Moreover, it’s shared with all I2C devices on the bus, so you can still have so many other modules/sensors connected on the same bus. In this previous article, We’ve demonstrated everything about this IC using its datasheet and build a driver library (in Embedded-C) for this IC. You can check it out if you’re interested in learning more about it.


In this tutorial, we’ll only discuss the important things that you need to know in order to get started with I2C LCD interfacing with STM32.

I2C LCD Address (Default)

You need to refer to the PCF8574 chip manufacturer’s datasheet to make sure what’s the I2C device address for the chip you’ve got around. If you’ve got an I2C LCD with Ti (Texas Instruments) PCF8574 chip, the default I2C address is 0x27 which is the 7-Bit device address with the three least significant bits (A0 – A1 – A2) are pulled up to HIGH.

If you’ve got an I2C LCD with an NXP PCF8574 chip, the default I2C address is therefore 0x3F. The question is what if we’d like to add multiple I2C LCDs to the I2C bus and control them with an STM32 microcontroller, how is that possible?

First of all, any I2C device on the bus must have a unique address. Therefore, we need to change the I2C address of the PCF8574 module if we’d like to add multiple units of it on the same I2C bus. Let’s next see how to do it!

Change I2C LCD Address

The I2C LCD interface (PCF8574) has 3 solder pads on the module’s board which control the value of the last 3 digits in the 7-Bit address of the device (A0 – A1 – A2). The pins are by default (internally) pulled up to HIGH (1), but if we short the solder pads together, this will drive the corresponding address bit pin to LOW (0). And that’s how we can change the device address.

ESP32 Multi I2C LCD Arduino Example

You can use the interactive tool below to check the I2C LCD device address after soldering any of the solder pads (A0, A1, or A2). There are 8 different combinations, which means we can connect up to 8 different I2C LCDs on the same bus with a single STM32 board and control all of them at the same time.

I2C LCD Address (Texas Instruments’ PCF8574)


I2C LCD Address (NXP’s PCF8574)

❕ Note

The I2C LCD module has a default I2C device address of either 0x27 or 0x3F depending on the hardware manufacturer. If you’re not quite sure about the device address, you can use this STM32 I2C Scanner application to detect the exact device address.

Using the solder pads on the PCD8574 module will enable you to set the low 3 address bits (A0-A1-A2). This means we can have up to 8 different address combinations and consequently be able to connect up to 8 I2C LCD units on the same I2C bus and control them with only one STM32 microcontroller.

STM32 I2C LCD Interfacing

Now, let’s move to interfacing the I2C LCD 16×2 display with STM32. Let’s check the pinout, wiring diagram, LCD contrast control, and the I2C LCD device address.

I2C LCD Pinout

The I2C LCD Display has only four pins. The pinout is shown below:


GND is the ground pin.

Vcc is the LCD’s power supply input pin (connects to +5v).

SDA is the serial data line for the I2C LCD interface.

SCL is the serial clock line for the I2C LCD interface.

Wiring I2C LCD With STM32 Blue Pill

Here is the wiring diagram for the I2C LCD display with STM32 Blue Pill board that we’ll be using in the examples hereafter in this tutorial.


Contrast Adjustment For I2C LCD

After connecting the I2C LCD module, you’ll be able to control the LCD contrast by using the PCF8574 module’s on-board potentiometer. Turn it to the right and to the left until you feel satisfied with the current contrast level.

Get The I2C LCD Address

If you’re not quite sure about the I2C LCD’s device address, you can use the code example below and run it on your STM32 board after connecting the I2C LCD display to your board. It’ll automatically detect and print out the I2C device address for the LCD over the serial monitor.

For more information about how to use this I2C scanner script, check its full tutorial linked below.

STM32 I2C Scanner HAL Example Code

This article will give you more in-depth information about the STM32 I2C Scanner application and how to use it to detect various I2C devices’ addresses.

STM32 I2C LCD Library (Driver)

Let’s now move on to the STM32 I2C LCD library that I’ve developed for this STM32 series of tutorials which is probably what we’ve searched for before landing on this article. In this section, we’ll explore the library files, functions, and configurations. So you can make the best use of it and also know how to modify or add any extra functionalities that your project needs.

In the next section, we’ll discuss how to integrate this STM32 I2C LCD library into your STM32 CubeIDE projects step-by-step.

STM32 I2C_LCD Library Directory & Files

The STM32 I2C_LCD library is part of the ECUAL (ECU abstraction layer) that we’re continuously building through this STM32 Series of Tutorials. The driver consists of 4 files: 2 core files (a header file & a source file) + 2 configuration files (a header & a source).

  • I2C_LCD.h
  • I2C_LCD.c
  • I2C_LCD_cfg.h
  • I2C_LCD_cfg.c

The STM32 I2C_LCD library needs you to also include the util library as a dependency because it uses the delay utility built into the util driver. The util library is also provided in the download section & code examples near the end of this tutorial.

STM32 I2C LCD Library APIs (Functions)

The core header file ( I2C_LCD.h) has all functions’ declarations (APIs) that we’ll be using in our application layer.

I2C_LCD.h File

I2C_LCD.c File

❕ Note

Note that all of the library interface functions have the first input argument as uint8_t which is inteded to be the index of the I2C_LCD instance you’re addressing. This library supports multiple instances of creation and individual addressing for multiple I2C_LCD display units. We’ll create an example for this multi-LCD application later on in this tutorial.

STM32 I2C LCD Library Configurations

The STM32 I2C_LCD library can be easily configured using the configuration files ending with (_cfg), and here is how it works. The configuration header file declares a struct that packs up all the configuration parameters into one variable type as shown below.

I2C_LCD_cfg.h File

The configuration parameter type declared above will allow the user to choose the following: (LCD instance index, I2C module’s handle pointer variable, the I2C device address, the LCD’s columns count, and the LCD’s rows count).

The configuration source file will have the actual configuration parameter variable creation and assignation. This is the file you need to edit in order to configure this STM32 I2C_LCD library. So you can assign the desired configuration parameters.

I2C_LCD_cfg.c File

Note that the I2C module’s handle is externed in the I2C_LCD_cfg.c file to be used by the driver code internally. If you’re using any other I2C module (like I2C2, I2C3, or multiple of them) those should also be externed in this file as well. So that the configuration structure is able to access those handle variables.

Also note that the configuration parameter structure is externed to the header file so that in the I2C_LCD.c source code we can include the configuration header file I2C_LCD_cfg.h and see that global config parameter and use it internally.

Download The ECUAL/ I2C_LCD Driver Folder

STM32 I2C LCD Library Integration

In this section, we’ll discuss how to integrate the STM32 I2C_LCD library into your projects step-by-step. Assuming you’ve downloaded the provided library files from the links in this tutorial or from the GitHub Repo for this STM32 Tutorials Series, here is how you can use it in action.

The steps below apply to any other driver (library) in the ECUAL software components directory.

Step #1

Configure The Required Hardware Peripherals in STM32CubeMX

The first step is to head over to STM32CubeMX, create a new project, and configure the hardware needed for the library.

STM32 I2C_LCD Library HW Requirements

  • 1x I2C Module (Default Configurations)
STM32 I2C LCD 16x2 20x4 CubeMX Configuration

You can choose any I2C module you want.

Add any other peripherals you need in your project and configure the RCC clock however you want. There is no conflict between the I2C_LCD library and any other hardware configurations you may do in CubeMX.

Once you’re done with CubeMX configurations, generate the project code and head over to STM32CubeIDE.

Step #2

Copy & Paste The Library Folders

Copy the provided library folders (ECUAL/I2C_LCD + util) and open the STM32CubeIDE.

In STM32CubeIDE, right-click the project name and paste the library folders.

STM32 LCD Display Library Code FilesSTM32 LCD Display Library Code ExampleSo it’ll look like this at the end:
STM32 LCD 16x2 Library Files

Step #3

Add The Library Directories To Paths & Symbols

The library folders have been added to our project but it’s not yet considered as a source code directory, so it won’t be compiled and give you a linking error in the linking stage if you call any of its functions.

Right-click the project name and click Properties. And navigate to C/C++ paths and symbols, and source locations tab. In the source locations tab, click add folder and add our library folders (ECUAL + util).

STM32 LCD Display 16x2 Library Example

Step #4

Configure The I2C_LCD Library Using The cfg Parameter

Open the I2C_LCD_cfg.c file and modify the configuration parameter items to match your hardware setup (the I2C module’s handle, I2C device address, and the actual LCD size).

Step #5

Include The Library Header File & Use it!

Now you’re ready to use the STM32 I2C_LCD library, just include the header file as shown in the test code below.

STM32 I2C LCD 16×2 Example

Objectives of This STM32 I2C LCD 16×2 Example Project:

  • Set up a new project in CubeMX, set the system clock @ 72MHz
  • Configure 1x I2C module required by the STM32 I2C LCD library
  • Integrate the STM32 I2C_LCD library as shown in the previous section (step-by-step)
  • Write a simple application to test the LCD driver code.

STM32 I2C LCD 16×2 Example Code [Project]

In this LAB, our goal is to test most of the functionalities provided by the I2C_LCD library that I’ve developed for this tutorial.

Follow The step-by-step Library Integration Guide shown earlier to create the project and add the I2C_LCD library folders. Copy the example application code below, build the project, and flash it to your STM32 blue pill board.

STM32 I2C LCD 16×2 Example Code

The Application Code For This LAB (main.c)

Testing Result (Demo Video)

❕ Note

The LCD has an internal Character Generator ROM (CGROM). The character generator ROM generates (5×8) dots or (5×10) dot character patterns from 8-bit character codes. It can generate 208 (5×8) dot character patterns and 32 (5×10) dot character patterns. User-defined character patterns are also available by mask-programmed ROM.

Given that the CGROM has 208 character patterns for (5×8) dot displays, this means that not all the 255 ASCII table characters are available by default in the LCD display. You can refer to this tutorial for more information about this. As we’re more interested in the LCD’s internal CGRAM.

In the Character Generator RAM (CGRAM), the user can write new custom character patterns. For (5×8) dots display, eight-character patterns can be written at maximum. Only 8 custom character seems like a small space but it’s what it’s and we’ll see how to use it in this example project.

STM32 LCD Custom Character Generator

You can use this online LCD Custom Character Generator Tool and it’ll give you the C-Code for it, which you can easily copy and paste into your project code. And here is how to use it:

Click on the pixels to draw your custom LCD character, you can invert or clear the entire display cell if you want with the buttons below. If you’re satisfied with how your icon/emoji looks, you can copy the code and you’re good to go. Here are some example custom characters generated by this tool.


I used my custom LCD character generator tool to create the above icons/emojis (heart, speaker, smiley face, notification bell, battery level indicator).

STM32 Multiple I2C LCD Example Code [Project]

In this example project, we’ll connect multiple I2C LCDs with our STM32 blue pill board and write different text messages to each of them. Obviously, we need to change the I2C LCD device address using the solder pads on the PCF8574 module’s board.

Hardware Changes For Multiple I2C LCD Support

In this example, I’ll connect two I2C LCD displays with my STM32 blue pill board. Therefore, I’ll leave one of them with the default address of 0x27 and will change the other I2C LCD’s address by shorting the A0 solder pads. This will change its address to 0x26 as shown in the figure below.

ESP32 Multi I2C LCD Arduino Example2

Software Changes For Multiple I2C LCD

In terms of software, nothing needs to be changed in our previous example project other than the configurations in the I2C_LCD_cfg.c file and also the definitions in the I2C_LCD.h header file. Let’s start by editing the I2C_LCD.h file by adding the following:

I’ve increased the I2C_LCD_MAX from 1 to be 2 as we’re going to use 2x I2C LCD displays in this project, and I’ve defined the index of the I2C_LCD_2 to be 1. And let’s now add the configuration structure for this newly added I2C_LCD instance in the I2C_LCD_cfg.c file that will be as follows:

As you might have noticed, adding a second I2C_LCD instance is just a matter of adding a new configuration structure into the I2C_LCD_CfgParam array and that’s all about it. We can now move to the application code in the main.c file.

STM32 Multiple I2C LCD Displays Example Code

The Application Code For This LAB (main.c)

Testing Result

STM32 Multiple I2C LCD Displays Library Example

STM32 I2C LCD Common Issues Troubleshooting

In this section, we’ll discuss some of the most common STM32 I2C LCD interfacing issues and how to troubleshoot those issues if you’re facing any of them in your project.

Garbage Characters Display

If your LCD is displaying garbage characters, it’s a strong indicator that there is an issue with data communication between your STM32 board and the I2C LCD module itself. Make sure your connections are correct and the device address is correct. The Default I2C address is 0x27 for Ti’s PCF8574 and 0x3F for NXP’s PCF8574 modules.

LCD Showing Black Boxes or Blank Display

This can be a contrast issue at the Vo pin, so make sure you’re connecting the contrast control potentiometer and turn it to the right and left until it’s properly set to an acceptable level.

Contrast is Ok, But Still Blank Display

This can be a power supply issue, make sure you’re connected to a stable +5v power supply. Sometimes powering from a USB port in a computer can cause power issues like this, so try using a power bank or a proper power supply and check if the issue is still persistent.

Using a poor power supply USB port, poor quality USB cables, or even USB extender cables can cause all sorts of power issues. And the LCD display module is sensitive to such issues that you’d not detect during LEDs and buttons example projects.

I’ve been using an external power bank with a USB cable into the STM32 blue pill USB port for providing power to multiple LCDs with no issues at all, so you can try that solution if you’re facing similar issues.

Required Parts For STM32 Examples

All the example Code/LABs/Projects in this STM32 Series of Tutorials are done using the Dev boards & Electronic Parts Below:

QTY.Component NameAmazon.comAliExpresseBay
1I2C LCD 16×2 DisplayAmazonAliExpresseBay
1STM32-F103 BluePill Board (ARM Cortex-M3 @ 72MHz)AmazonAliExpresseBay
1Nucleo-L432KC (ARM Cortex-M4 @ 80MHz)AmazonAliExpresseBay
1ST-Link V2 DebuggerAmazonAliExpresseBay
1LEDs KitAmazonAmazonAliExpresseBay
1Resistors KitAmazonAmazonAliExpresseBay
1Capacitors KitAmazonAmazonAliExpress & AliExpresseBay & eBay
1Jumper Wires PackAmazonAmazonAliExpress & AliExpresseBay & eBay
1Push ButtonsAmazonAmazonAliExpresseBay
1Micro USB CableAmazonAliExpresseBay

★ Check The Links Below For The Full Course Kit List & LAB Test Equipment Required For Debugging ★

Download Attachments

You can download all attachment files for this Article/Tutorial (project files, schematics, code, etc..) using the link below. Please consider supporting our work through the various support options listed in the link down below. Every small donation helps to keep this website up and running and ultimately supports the whole community.

Wrap Up

In conclusion, we’ve discussed how the STM32 I2C_LCD library works and how to integrate it into your projects and easily configure the I2C LCD 16×2 and/or 20×4. The provided library gives you a handful of useful APIs that you can use in your projects to control a single LCD 16X2 unit or multiple display units with no effort.

If you’re just getting started with STM32, you need to check out the STM32 Getting Started Tutorial here.

Follow this STM32 Series of Tutorials to learn more about STM32 Microcontrollers Programming.

Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

2 thoughts on “STM32 I2C LCD Library & Examples (16×2, 20×4, Multiple LCDs)”

Leave a Comment