OLED display using I2C with STM32

I already covered how to connect LCD 16×2 using I2C in STM32. Today we will take a step forward and interface OLED display using I2C with STM32.

The display I will be using is a 0.96″ 128×64 oled display with black and blue colors.

  • 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 as I mentioned before, the code will remain 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

HOW TO

Let’s see the Setup Process First.

Below is the image from the CubeMX

  • Select the FAST MODE in the I2C, as it is required for the OLED Display
  • The SCL and SDA Pins will get automatically selected.
  • You can use the Pull Up register to these 2 Pins.

The Connection is as shown Below


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.

Include the following files in the main.c:-

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

Open the ssd1306.c and change the handler accordingly 

extern I2C_HandleTypeDef hi2c1;

You can see the functions available in the functions tab under ssd1306.c or in the ssd1306.h file. I am going to initialize the display and print “Hello World !!”…

SSD1306_Init (); // initialize 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




You can scroll the display LEFT, RIGHT, DIAGONAL LEFT or DIAGONAL RIGHT also. The following are the functions available to do so.

void SSD1306_ScrollRight(uint8_t start_row, uint8_t end_row);

void SSD1306_ScrollLeft(uint8_t start_row, uint8_t end_row);

void SSD1306_Scrolldiagright(uint8_t start_row, uint8_t end_row);

void SSD1306_Scrolldiagleft(uint8_t start_row, uint8_t end_row);

void SSD1306_Stopscroll(void);

The colour of the display can be inverted using void SSD1306_InvertDisplay (int i);
i=1 will invert the display
i=0 will normalise it.


Drawing bitmap is also supported and the following function is assigned to do so

/**
 * @brief  Draws the Bitmap
 * @param  X:  X location to start the Drawing
 * @param  Y:  Y location to start the Drawing
 * @param  *bitmap : Pointer to the bitmap
 * @param  W : width of the image
 * @param  H : Height of the image
 * @param  color : 1-> white/blue, 0-> black
 */
void SSD1306_DrawBitmap(int16_t x, int16_t y, const unsigned char* bitmap, int16_t w, int16_t h, uint16_t color);

We can also display the animation. Check out the video below, to see, how to do it.



Result

Check out the Video Below










Info

You can help with the development by DONATING
To download the code, click DOWNLOAD button and view the Ad. The project will download after the Ad is finished.

75 Comments. Leave new

  • 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.”

    Reply
  • 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

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

    Reply
  • Andre Santos
    August 8, 2022 3:48 AM

    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.

    Reply
  • 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.

    Reply
  • Ibrahim KHADRAOUI
    January 25, 2022 5:15 AM

    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!

    Reply
  • if u have possible provide with spi interfacing

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

    Reply
  • 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.

    Reply
  • George Robertson
    April 26, 2021 3:00 AM

    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.

    Reply
  • Luis Moises Lopez Lopez
    April 22, 2021 9:45 PM
    extern I2C_HandleTypeDef hi2c1;
    

    what function has this code line?

    Reply
  • Luis Moises Lopez
    March 19, 2021 7:30 AM

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

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

    Reply
  • why it is can not downloaded

    Reply
  • Thank you for your good writing and explanation.

    Reply
  • 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?

    Reply
  • 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” {

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

    Reply
  • Can Anyone send me the library for SSD1309 for STM32?

    Reply
  • Alperen KOLAMUÇ
    December 2, 2020 7:59 PM

    good work

    Reply
  • Alperen KOLAMUÇ
    December 2, 2020 7:58 PM

    good work

    Reply
  • 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

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

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

    Reply
  • 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

    Reply
  • 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

    Reply
  • 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

    Reply
  • Mitchell Kelly
    August 1, 2020 6:58 PM

    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

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

    Reply
  • 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

    Reply
  • Giovanni Sánchez
    June 18, 2020 9:53 AM

    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?

    Reply
  • Atir Sharif
    May 18, 2020 1:25 AM

    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

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

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

    Reply
  • 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.

    Reply
  • pablito Tapiales
    August 11, 2019 8:17 PM

    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

    Reply
  • Works very well on my STM32F407 board, Thank you!

    Reply
  • 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 😉

    Reply
  • /* 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??

    Reply
  • /* 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?

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

    Reply
    • google it. It depends on what IDE you are using.

      Reply
    • pablito Tapiales
      August 12, 2019 7:56 AM

      /* 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();
      }

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

    Reply
  • ramin_javadi
    July 17, 2018 12:45 PM

    thanks….
    it was fantastic

    Reply
  • Oleksandr Gusiev
    May 20, 2018 9:36 PM

    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.

    Reply
    • Oleksandr Gusiev
      May 26, 2018 1:30 AM

      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.

      Reply
  • many thanks for this, really good c code

    Reply
  • 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);
    }

    Reply
  • thanks,very professional and useful.

    Reply
  • 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!

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

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

keyboard_arrow_up

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add controllerstech.com to your ad blocking whitelist or disable your adblocking software.

×