Interface SH1106 1.3″ OLED with STM32 via I2C

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.

Interface SH1106 1.3″ OLED with STM32 via I2C

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.

SH1106 Display

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.

STM32 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

STM32 Oled Display COnnection

As shown in the image above:

Display PinSTM32 ConnectionDescription
VCC3.3V from STM32Powers the SH1106 OLED display
SCLI2C Clock Pin on STM32I2C clock line connection
SDAI2C Data Pin on STM32I2C 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.

STM32 SH1106 Working

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.

STM32 SH1106 Working

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.

Image generator

Once you click Convert, the c file containing the image array will download. We will copy the array to our project.

Image data
#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.

STM32 SH1106 Working

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.

You May Also Like..

Subscribe
Notify of

3 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Amit
8 months ago

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?

Amit
8 months ago

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?

Sharil Shafie
Reply to  Amit
3 months ago

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.

Last edited 3 months ago by Sharil Shafie

🛈 Advertising Disclosure

This website relies on advertisements as its main source of revenue to support the creation of free, high-quality content.
If you enjoy our work and would like to help us continue, please consider disabling your ad blocker while browsing here.

Your support truly makes a difference — thank you!

Share this Article

Recent Posts

Join Our Community

Weekly Newsletter

Subscribe to our newsletter to get our news