The more we know the harder it is to defeat us!


Recently, I have come to a conclusion that it would be good to print the state of my quadrocopter on a display. The question was what kind of display should I use. I decided to give a try to a small 0.96″ OLED display with I2C interface. It is based on SSD1603 driver. You can see this display on the image above. However, there was an issue regarding the screen controller. But it was soon solved. I have come across the U8glib which is a graphic library, quite popular among Arduino users. As soon as I started to read about the library I realized that it does not support STM32, not mentioning the HAL library.

Well, I have solved that ūüėČ

Some time ago I have described the HAL library from STMicroelectronics along with SPL and other solutions. I have found that other people have already started some work regarding the U8glib for STM32. This blog post describes a general rule how a communication interface should be ported. However, the Author is using the SPL. The approach can be generalized and used to write a driver for STM32 HAL.

How does the U8glib works?

What is the most important thing about the U8glib is that there are abstraction layers. You can divide the code roughly in four parts:

  • Physical layer (COM),
  • Device layer (DEV),
  • Drawing routines,
  • Miscellaneous.

This makes porting drivers to different platforms a lot easier. The Author of the U8glib separated device routines, the driver itself, from the hardware layers. This allows a developer to focus on the part on which he or she wants to. If you are not interested in what you should send to the display to initialize it and instead you would like to work closer to the hardware you can focus only on the hardware abstraction layer (HAL, what a coincidence :)).

To create an instance, device with communication interface union, you have to write a line of code like below.

This binds the device with the communication layer. Say, if you want to draw a line and you know you have to send 0x12 0x00 0x00 0x2F 0x1F to the display you do not have to worry about it. The device layer sends it to the physical layer and that’s all. Now, it is the physical layer’s task to actually transmits the data to the display.

Physical layer interface

The function responsible for handling communication has a template like this one below

  • U8G_COM_MSG_STOP: stop the device,
  • U8G_COM_MSG_INIT: initialize the device,
  • U8G_COM_MSG_ADDRESS: defines data or command mode (command mode for arg_val = 0),
  • U8G_COM_MSG_CHIP_SELECT: chip select (valid for SPI interface),
  • U8G_COM_MSG_RESET: reset the device (valid for devices with reset port),
  • U8G_COM_MSG_WRITE_BYTE: write single byte,
  • U8G_COM_MSG_WRITE_SEQ: write byte sequence to device,
  • U8G_COM_MSG_WRITE_SEQ_P: write byte sequence to device from flash (program memory).

Solution to the problem

Soon I have found a different attempt to port the driver for the OLED display. The Author is clearly using the same template I have found in the first article. However, there are some issues, mainly two. The first one is how memory is handled. The Author is coping the data that is going to be send to a buffer with below routine:

It is not very efficient way to send data, or copy the date on 32-bit MCU. Firstly, you lose time to copy the data and secondly you waste memory for it. Of course, now the microcontrollers have more and more resource but if you can save them than why not? The second issue is referred to the amount of data you want to send. It should be actually arg_val + 1 because you send one extra byte.

Having all this covered I prepared my own implementation of the driver for SSD1603 screen controller.

And the header file:

As you can see I am using HAL_I2C_Mem_Write() function instead of HAL_I2C_Master_Transmit(). This allows you to send an extra byte/bytes followed by actual data. In this way you do not have to copy it manually to a buffer. Basically, HAL_I2C_Mem_Write() plainly concatenates two chunks of data by sending one after another. This is commonly used i.e. for data transfer with sensors like accelerometers, magnetometers, etc. Firstly, you have to point a register address to which you want to write to or read from and after that the data should follow.

How to use the driver?

To use the driver you have to do a few simple steps. Firstly, prepare your project. You can do this with STM32CubeMX. Create a *.c file, mine source file is u8g_com_arm_stm32.c and the header file is u8g_com_arm_stm32.h. Put the code listed above to the files and add them to your project. This is pretty much it. You can use below sample code to display “Hello World!” text on the screen:

Files to download:

The driver is available at Github:


Also there is an example running on STM32F103C8T6 development board:


7 Responses to STM32 HAL driver for I2C OLED display with U8glib (Updated)

  • George says:

    Hello. I have a STM32F103C8T6 board and a same display as you. From the start I will like to say that I’m a noob with the STM32F103 board. First of all can you tell me how to wire the board to the display. Second can you tell me what files need to go were and can you give me a simple sketch example for the Arduino IDE that I can use to display a simple text line? Thanks and have a nice day.

Leave a Reply

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


If you like my blog please consider a small donation.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 220 other subscribers