Learn to interface a 1.3″ SH1106 OLED with STM32 via I2C. Includes wiring on STM32 I2C pins, CubeMX setup, init code, text, bitmaps & display offset handling. The project is available to download at the end of this post.

Also Read:
Introducing SH1106 1.3″ Oled Display
The SH1106 1.3″ OLED display is a monochrome graphical screen commonly used in embedded systems for displaying text, graphics, and sensor data. It features a resolution of 128×64 pixels and uses either I2C or SPI communication protocols. With its bright contrast and low power usage, it’s ideal for small interface displays in STM32, Arduino, and ESP32 projects.

Some of its important features are:
- 128×64 pixel resolution with 1.3″ diagonal size
- Supports I2C and SPI communication
- Monochrome white/blue OLED display with high contrast
- Compatible with many microcontrollers like STM32, Arduino, ESP32
CUBEMX CONFIGURATION
Below is the image showing the I2C configuration.
- I am using I2C1 to interface the display.
- The I2C is configured in the FAST MODE. This is as required by the OLED Display
- The pins PB6 and PB7 are configured as SCL and SDA pins.
WIRING DIAGRAM
The Connection between STM32 and Oled display is as shown Below
As shown in the image above:
Display Pin | STM32 Connection | Description |
---|---|---|
VCC | 3.3V from STM32 | Powers the SH1106 OLED display |
SCL | I2C Clock Pin on STM32 | I2C clock line connection |
SDA | I2C Data Pin on STM32 | I2C data line connection |
THE CODE
Configuration
Open the SH1106.c and change the I2C handler according to your setup.
extern I2C_HandleTypeDef hi2c1;
#define SH1106_I2C &hi2c1
Also configure the display resolution in the SH1106.h file.
/* SH1106 width in pixels */
#ifndef SH1106_WIDTH
#define SH1106_WIDTH 128
#endif
/* SH1106 LCD height in pixels */
#ifndef SH1106_HEIGHT
#define SH1106_HEIGHT 64
#endif
The SH1106 IC supports 132×64 pixels. Therefore we would need to centre our 128×64 region within this range. In doing so, there will be an offset (of 2px) in the x-axis from both the ends. Although we do not need to worry about the offset in the end, but we definitely need to consider the offset in the beginning.
So if you want print something at x=0, instead you would need to print it at x=2.
You can see the functions available in the functions tab under SH1106.c or in the SH1106.h file.
Print simple strings
#include "<strong>SH1106</strong>.h"
#include "fonts.h"
int main()
{
.....
SH1106_Init (); // initialise the display
SH1106_GotoXY (12,10); // goto 10, 10
SH1106_Puts ("HELLO", &Font_11x18, 1); // print Hello
SH1106_GotoXY (12, 30);
SH1106_Puts ("WORLD !!", &Font_11x18, 1);
SH1106_UpdateScreen(); // update screen
while (1) { }
}
- Here we will first initialise the display in the main function.
- Then set the cursor at x=12, y=10 and print “HELLO” at this location. Considering the offset, the cursor is actually at 10,10.
- Set the cursor at x=12, y=30 and print “WORLD !!” at this location.
- We need to call the function SH1106_UpdateScreen to update the display with the modified content.
Below is the image showing the output of the above code.
Print Numbers
Any display does not support printing the numbers directly on it. Instead we need to change the number into the equivalent Ascii characters and then print it.
Below the code shows how to print integer and floats.
#include "SH1106.h"
#include "fonts.h"
#include "stdio.h" // for sprintf
int main()
{
.....
int num = 123456; float flt = 123.45;
char bufnum[7]; char bufflt[7];
SH1106_Init (); // initialise the display
sprintf (bufnum, "%d", num);
sprintf (bufflt, "%.2f", flt);
SH1106_GotoXY (12,10); // goto 10, 10
SH1106_Puts (bufnum, &Font_11x18, 1); // print Hello
SH1106_GotoXY (12, 30);
SH1106_Puts (bufflt, &Font_11x18, 1);
SH1106_UpdateScreen(); // update screen
while (1) { }
}
- Here we will first initialise the display in the main function.
- Then define the character buffers to store the converted integer and float values.
- The sprintf function is used to convert the integer(%d) and float(%f) values to the respective Ascii format.
- Then set the cursor at x=12, y=10 and print num at this location.
- Set the cursor at x=12, y=30 and print flt at this location.
- We need to call the function SH1106_UpdateScreen to update the display with the modified content.
Below is the image showing the output of the above code.
Bitmaps
We can draw a bitmap image anywhere on the display. We just need to convert the bitmap image to c array format. This tool can do that.
Make sure to choose the configuration as shown below.
Once you click Convert, the c file containing the image array will download. We will copy the array to our project.
#include "SH1106.h"
#include "fonts.h"
#include "stdio.h" // for sprintf
#include "bitmap.h"
int main()
{
.....
SH1106_Init();
SH1106_DrawBitmap(2, 0, logo, 128, 64, 1); // offset 2, so cursor is at 0,0
SH1106_UpdateScreen(); // update screen<p style="margin:0;"></p> while (1) { }
}
- Here we will first initialise the display in the main function.
- Then draw the bitmap defined in the bitmap.h file.
- The bitmap start position is set to x=2,y=0.
- The size is 128pixels x 64pixels.
- We need to call the function SH1106_UpdateScreen to update the display with the modified content.
Below is the image showing the output of the above code.
VIDEO TUTORIAL
You can check the video to see the complete explanation and working of this project.
Check out the Video Below
PROJECT DOWNLOAD
Info
You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.
Hi, thanks for the detailed explanation. Finally, I got my display working. But one problem I am facing is a vertical white band at the left side of the display. What could be the probable cause & how can I rectify it?
Hi, thanks for the detailed explanation. Finally, I got my display working. But one problem I am facing is a vertical white band at the left side of the display. What could be the probable cause & how can I rectify it?
I think the codes are not fully compatible with SH1106. So I make some changes.
Change the corresponding line in SH1106_UpdateScreen function in SH1106.c to this:
SH1106_WRITECOMMAND(0xB0 + m);
SH1106_WRITECOMMAND(2 & 0xf);
SH1106_WRITECOMMAND(0x10 | (2 >> 4));
SH1106_I2C_WriteMulti(SH1106_I2C_ADDR, 0x40, &SH1106_Buffer[SH1106_WIDTH * m], SH1106_WIDTH);
The changes is based on the solution as provided in this link. I post this the moment I got this to work, so there might be something else that I haven’t taken into account.