Interface SSD1306 OLED display with STM32

I already covered how to interface LCD 16×2 using I2C with STM32 and how to interface 1.3″ SH1106 oled display with STM32. Today I have another Oled display with me, It is a 0.96″ SSD1306 OLED display and we will interface it using I2C.

  • This display uses the I2C protocol to communicate to the microcontroller. So here you need only 2 pins i.e. SDA and SCL from the microcontroller and the VCC and GND. 
  • I am using STM32f103c8t6  but the code will remain the same for all STM32 devices. 
  • I searched a lot for the libraries but all I could find were that of arduino. Than at last I found one by Alexander Lutsai, and I modified it so that it can be used with the STM32 CubeMx

CubeMX Configuration

Below is the image showing the I2C configuration.

  • Set the I2C in the FAST MODE, as it is required for the OLED Display
  • The SCL and SDA Pins will get automatically selected.

The Connection is as shown Below

As shown in the image above:

  • The display is powered with 3.3V from the STM32 board itself.
  • The SCL and SDA pins are connected to their respective counterparts on the board.


The Code

Open the ssd1306.c and change the I2C handler according to your setup.

extern I2C_HandleTypeDef hi2c1;
#define SSD1306_I2C &hi2c1

Also configure the display resolution in the ssd1306.h file.

/* SSD1306 width in pixels */
#ifndef SSD1306_WIDTH
#define SSD1306_WIDTH            128
#endif
/* SSD1306 LCD height in pixels */
#ifndef SSD1306_HEIGHT
#define SSD1306_HEIGHT           64
#endif

You can see the functions available in the functions tab under ssd1306.c or in the ssd1306.h file.

Print simple strings

#include "ssd1306.h"
#include "fonts.h"

int main()
{
  .....
  SSD1306_Init (); // initialise the display 
  SSD1306_GotoXY (10,10); // goto 10, 10 
  SSD1306_Puts ("HELLO", &Font_11x18, 1); // print Hello 
  SSD1306_GotoXY (10, 30); 
  SSD1306_Puts ("WORLD !!", &Font_11x18, 1); 
  SSD1306_UpdateScreen(); // update screen
  while (1) { }
}  
  • Here we will first initialise the display in the main function.
  • Then set the cursor at x=10, y=10 and print “HELLO” at this location.
  • Set the cursor at x=10, y=30 and print “WORLD !!” at this location.
  • We need to call the function SSD1306_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 "ssd1306.h"
#include "fonts.h"
#include "stdio.h"  // for sprintf

int main()
{
  .....
  int num = 123456; float flt = 123.45;
  char bufnum[7]; char bufflt[7];
  SSD1306_Init (); // initialise the display 
  sprintf (bufnum, "%d", num);
  sprintf (bufflt, "%.2f", flt);
  SSD1306_GotoXY (10,10); // goto 10, 10 
  SSD1306_Puts (bufnum, &Font_11x18, 1); // print Hello 
  SSD1306_GotoXY (10, 30); 
  SSD1306_Puts (bufflt, &Font_11x18, 1); 
  SSD1306_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=10, y=10 and print num at this location.
  • Set the cursor at x=10, y=30 and print flt at this location.
  • We need to call the function SSD1306_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 "ssd1306.h"
#include "fonts.h"
#include "stdio.h"  // for sprintf
#include "bitmap.h"

int main()
{
  .....
  SSD1306_Init();
  SSD1306_DrawBitmap(0, 0, logo, 128, 64, 1);
  SSD1306_UpdateScreen(); // update screen

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=0,y=0.
  • The size is 128pixels x 64pixels.
  • We need to call the function SSD1306_UpdateScreen to update the display with the modified content.

Below is the image showing the output of the above code.


Scrolling and Animation

The SSD1306 has support for scrolling at hardware level. There are registers in the SSD1306 IC which enable the display to scroll in different directions.

The following are the functions available to do so.

#include "ssd1306.h"
#include "fonts.h"
#include "stdio.h"  // for sprintf
#include "bitmap.h"

int main()
{
  .....
  SSD1306_Init();
  SSD1306_DrawBitmap(0, 0, logo, 128, 64, 1);
  SSD1306_UpdateScreen(); // update screen

  SSD1306_ScrollRight(0x00, 0x07);    // scroll entire screen (Page0 to Page7) right
  HAL_Delay (5000);
  SSD1306_Stopscroll();

  SSD1306_ScrollLeft(0x00, 0x07);    // scroll entire screen (Page0 to Page7) right
  HAL_Delay (5000);
  SSD1306_Stopscroll();

while (1) { } }

In the code above, we are scrolling the entire screen in the right direction for 5 seconds, and then in the left direction for another 5 seconds. The screen contains the bitmap on it and therefore we will see the bitmap scrolling.

The Animation part is explained in the video shown below. Please check out the video to see the complete working.



Result

Check out the Video Below




Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

Subscribe
Notify of

76 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Hosein
1 year ago

Hello there, how do I add some new/custom fonts instead of using the inner fonts in library files?

Sherbeen
1 year ago

I cannot find where to download the following?? Can you please direct me where to find these files that you mentioned?

”Download the code below, unzip it, Copy the fonts.h, test.h and ssd1306.h in the Inc folder of your project, and fonts.c, test.c and ssd1306.c in the Src folder and open the project now.”

Denis
2 years ago

Thank you for very good tutorial. Example runs with minor modification (PB6 & PB7 –> PB8 , PB9) also on NUCLEO-F411RE board and stmcube ide 1.11.0

Maxi Lara
2 years ago

Would it work in any I2C OLED 128×64 display? and 256×64?

Andre Santos
2 years ago

Hi. I am trying to add more fonts. But I did’nt find any program to output 32bit format font archive. Only 8 bit format! Could you tell me wich program did you use? Thanks a lot.

seth
Reply to  Andre Santos
2 years ago

Hi, have you found how to create front ?

Adrian
3 years ago

Great tutorial and well explained. One small change I made to your SSD1306_DrawBitmap function. You can add “else SSD1306_DrawPixel(x+i, y, 0);” right after the if statement to draw a black pixel instead of white. This will make for a very smooth horse running and eliminates the need to clear the screen following each call to DrawBitmap. Thanks again for the awesome video.

Ibrahim KHADRAOUI
3 years ago

Hello Sir,
Thank you for the tutorial it’s awesome and very helpful, I have just one question, can I use this SSD1306 library with FreeRTOS, I think it will be very interesting, we could use an SD card with bitmaps in it and print them on the screen with the OLED display.
Thanks, Sir!

Last edited 3 years ago by Ibrahim KHADRAOUI
ram
3 years ago

if u have possible provide with spi interfacing

Jake Mangels
3 years ago

I am having a problem in ssd1306.c with undefined references to ‘hi2c1’. What fixes can I do?

zhengtata
Reply to  admin
2 years ago

i have enabled i2c in cubeMX,why i have the same problem? maybe because there exist 2 i2c?

Harshit
3 years ago

That’s a really helpful tutorial. I want to know if I can connect MPU6050 and the LCD to the same pins at the same time (using I2C only). Will the config of any affect the other.

Harshit
Reply to  admin
3 years ago

Thanks a lot!! I really Appreciate it!

George Robertson
4 years ago

Hi, I really liked the tutorial, I wandering if this code can be used for a NUCLEO-F446RE (STM32F446RE)? I have been trying to make it work but I haven’t been able to. Thanks.

Carl
Reply to  George Robertson
3 years ago

Yes , check this video https://www.youtube.com/watch?v=Z6VyFYzQWSs. Just need to change #include “stm32f1xx_hal.h” to f4 inside ssd1306.h.

Luis Moises Lopez Lopez
4 years ago
extern I2C_HandleTypeDef hi2c1;

what function has this code line?

Luis Moises Lopez
4 years ago

I don´t have money for you but, I would like to tell you “I LOVE YOU S MUC FOR THIS.”

NHY
4 years ago

Is it possible to interface the lcd 128x32u using your library?

govardhan
4 years ago

why it is can not downloaded

stmstart
4 years ago

Thank you for your good writing and explanation.

Milad
4 years ago

Hello,
Thank you .
I downloaded the zip file and tried to build the project.
But I have below error :
./Inc/fonts.h:41:10: fatal error: stm32f1xx_hal.h: No such file or directory

What do you think? Can you share me this library please?

Last edited 4 years ago by Milad
stmstart
Reply to  Milad
4 years ago

It works if you change to the same header file as the MCU you use.

Zain
4 years ago

Thanks for this tutorial! Excellent job! I ran into a problem compiling the code first time in a C++ project in STM32CubeIDE: “error: ‘C’ does not name a type; did you mean ‘_C’?” Needed to add quotation marks on C to get it to compile correctly: extern “C” {

Abhay Garg
4 years ago

Hi,
Where is the link for all these libraries which you are mentioned in the above tutorials?

Milad
Reply to  Abhay Garg
4 years ago

If you click on the download but the download does not start, you right click on the download button then copy the address of the line then paste in the search bar.

Zeroache277
Reply to  Milad
2 years ago

The link is obviously broken.. link to a github repo would be much better

Chaitanya
4 years ago

Can Anyone send me the library for SSD1309 for STM32?

Alperen KOLAMUÇ
4 years ago

good work

Alperen KOLAMUÇ
4 years ago

good work

ebe
4 years ago

hi there, really good thanks.. may i ask, could this ssd1306 driver be repurposed for a ssd1327 (128×128) i2c oled ? im using the same ssd1306 code with a different init sequence, however the oled simply doesnt display anything.. any help would be appreciated.. kind thanks

Brandon
4 years ago

Hi! Thanks, it worked perfectly. Is there any LCDAssistant avaliable for Linux distributions?

Serge
4 years ago

Good afternoon. Tell me how you can edit your code to use a smaller buffer?

Abhinav Jha
4 years ago

Brother I started the Payment Process but it says you have exceeded the limit for receiving any more funds.
If this resolves just reply.
Thanks for this contribution

Mukesh kumar
4 years ago

Hello,
I need ssd1306 code for stm8s controller. Actually i have done this , but the problem i am facing is font or size. I am not able to change the size of the letter in my code.
The library i used is from this site.
Please help me out how can i change the size.
http://embedded-lab.com/blog/stm8-microcontrollers-final-chapters/3/

Please help me out how can i change the size.
Thanks you.
m.k.verma795@gmail.com

Gottlieb
4 years ago

hello sir i want ask you something, i make this code to stm32 bluephill and then i get error selected processor does not support `dsb 0xF’ in Thumb mode

Mitchell Kelly
4 years ago

Hallo awesome library
only i have this following error message and i dont know how to get around it can you please help me with it?

.\Objects\OLED_i2c.axf: Error: L6218E: Undefined symbol Font_11x18 (referred from main.o).
.\Objects\OLED_i2c.axf: Error: L6218E: Undefined symbol SSD1306_GotoXY (referred from main.o).
.\Objects\OLED_i2c.axf: Error: L6218E: Undefined symbol SSD1306_Init (referred from main.o).
.\Objects\OLED_i2c.axf: Error: L6218E: Undefined symbol SSD1306_Puts (referred from main.o).
.\Objects\OLED_i2c.axf: Error: L6218E: Undefined symbol SSD1306_UpdateScreen (referred from main.o).
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.
Finished: 2 information, 0 warning and 5 error messages.
“.\Objects\OLED_i2c.axf” – 5 Error(s), 0 Warning(s).

Edit:
Nevermind i fixed it already, i was using Keilv5 IDE, where you cannot just copy paste into the source and inc folder, but you have to add the item to the group by right clicking,
and then i modify it for my stm32f030xx and it worked fine, thank you again

Last edited 4 years ago by Mitchell Kelly
yaniv
4 years ago

thank you for your code just send you a coffee , you saved me some times

hadi alavi
4 years ago

i want sent u donate but we are Boycott bye united state.
very very very thanks 🙂
the best likable aspiration for you.
Thanks Again
from IRAN

Last edited 4 years ago by hadi alavi
Giovanni Sánchez
4 years ago

hi! excellent project, but I have a problem. when I download the .zip, i don´t see any libraries fonts.h, test.h, and ssd1306.h, and neither do libraries fonts.c, test.c and ssd1306.h; but I do see libraries font.d and font.o, likewise with test and ssd1306. Are these libraries similar to .c and .h?

Atir Sharif
4 years ago

HI
IT IS VERY HARD TO SWITCH ON STM32 FROM AVR 8 BIT BUT YOU DID A GREAT JOB FOR ALL PEOPLE LIKE ME . THANKS

Johann dJ
5 years ago

Thank you for the example, got it working on Nucleo-L476RG board

T C
5 years ago

Was anyone able to get this to work on a STM32F466RE?

Joao Pifer
5 years ago

I adapted the code for Nucleo-32, it works perfectly but sometimes it stops working for no reason.
Once the display just scrolled down alone and almost half-top was the bottom part of the display. Then I disassembled the display to try to reset it or something but when I assembled it again it stopped working. This happened to me before but without de scrolling.

The code works perfectly, I was just adjusting some parameters. I have searched some information about it and some people says it’s because of using the nucleo’s power supply but it doesn’t work when I put an external input voltage to the display. Other people says that it is because its power supply is 3V3 not 5V as in this guide but I have also tried it and guess what, sometimes it works and but when you disassemble the display it doesn’t.

If anyone knows why this happens please tell me.

pablito Tapiales
5 years ago

MUCHAS GRACIAS. It works perfectly, you saved my day, I didn’t know how to use it in keil. Thank you so much.
STM32F103 (BLUE-PILL)
SCK (oled) to PB6
SDA(oled) to PB7

Mampfi
5 years ago

Works very well on my STM32F407 board, Thank you!

GLett
6 years ago

A detail…
The ssd1306_I2C_WriteMulti() function has a little bug in the counters, that is the reason why @Oleksandr Gusiev had to change SSD1306_WIDTH 128 to 129
Here is the fix

void ssd1306_I2C_WriteMulti(uint8_t address, uint8_t reg, uint8_t* data, uint16_t count) {
uint8_t dt[256];
dt[0] = reg;
uint8_t i;
for(i = 0; i < count; i++)
dt[i+1] = data[i];
HAL_I2C_Master_Transmit(&hi2c1, address, dt, count+1, 10);
}

I hope it can help to another freaky electronic lover like us 😉

Denis
6 years ago

/* USER CODE BEGIN Includes */
#include “ssd1306.h”
#include “i2c-lcd.h”
/* USER CODE END Includes */
Why i2c-lcd.h in code exists,but in video are not??

Denis
6 years ago

/* USER CODE BEGIN Includes */
#include “ssd1306.h”
#include “i2c-lcd.h”
/* USER CODE END Includes */
Why i2c-lcd.h in code exists,but in video are not?

Liberman
6 years ago

How I can Put float number from adc in the display?

pablito Tapiales
Reply to  Liberman
5 years ago

/* Private variables ———————————————————*/

//variable para LCD
char buf[25];
int dato=1;
…….
…….
while (1)
{

dato +=1;
if(dato>1000)
dato = 5;
dato = ((float)dato/24); // for example
sprintf(buf,”Dat:%.1f”,dato); //convert dato to string
SSD1306_GotoXY (0,0);
SSD1306_Puts (buf, &Font_11x18, 1);

SSD1306_UpdateScreen(); //Update the LCD
//End of LCD display

HAL_Delay(100);
SSD1306_Clear();
}

Sandip Maurya
6 years ago

Thanks Working good,
please tell me command to clear lcd.

ramin_javadi
6 years ago

thanks….
it was fantastic

Oleksandr Gusiev
6 years ago

Hello. I followed your guide. Thanks a lot, it helped me clarify some points, but i have some troubles. First of all https://goo.gl/XD3yQC there are some dots at right side of screen (tested on two screens, same problem). And the second, but the most important, during run in debug, screen looks https://goo.gl/UMFquG at any
debug step, and it is always so when boot pins in such a state. Please, relpy, if possible. Thanks.

Oleksandr Gusiev
Reply to  Oleksandr Gusiev
6 years ago

I fixed this issues. First problem with point to the right – bug into the lib. You should change #define SSD1306_WIDTH 128 in ssd1306.h to 129, cause numeration is starts from zero, not 1. The second problem was it that, I changed boot pins to 1. Both should be at 0.

pablito Tapiales
Reply to  Oleksandr Gusiev
5 years ago

In mi OLED work #define SSD1306_WIDTH 130

thorben
6 years ago

many thanks for this, really good c code

6 years ago

Hi, thanks for the explanation, I’m trying to port this code to a STM32L4 family.
I have managed to change all STM32f1xx lines. As well as changes the I2C number that I’m using hi2c3.

What’s is strange is that I’m getting only one error now which is on a completely different part of the code. It’s telling me the variable “count” needs a constant value. So maybe it’s not receiving anything.

void ssd1306_I2C_WriteMulti(uint8_t address, uint8_t reg, uint8_t* data, uint16_t count) {
uint8_t dt[count + 1];
dt[0] = reg;
uint8_t i;
for(i = 1; i <= count; i++)
dt[i] = data[i-1];
HAL_I2C_Master_Transmit(&hi2c3, address, dt, count, 10);
}

martin
6 years ago

thanks,very professional and useful.

JM
7 years ago

Thank you very much! I’ve used this display in my project following your post and it works perfectly! Please, keep doing more stm32 tutorials, very interesting and useful!

Lee Thuc
7 years ago

Hi there! If I connect directly sda and scl wires without external resistor, Is it ok?

TD
Reply to  admin
6 years ago