Popis použití OLED displeje SSD1306 v projektech na Raspberry Pi Pico a Pico-SDK. Monochromatický OLED displej komunikuje pomocí I2c sběrnice, má velikost 128 bodů na šířku a 32 bodů na výšku. Obvykle se prodává v barvě bílé, žluté a modré. Napájecí napětí displeje je 3.3 V.
C knihovna pro OLED displej umí psát písmenka v kódování UTF-8. K dispozici jsou fonty:
-
Font 9x15
-
Font 10x20 (5205 znaků).
-
Spleen 5x8 (728 znaků — latinka včetně češtiny, braille) — font je velmi malý
-
Spleen 6x12 (676 znaků)
-
Spleen 8x16 (1019 znaků — latinka včetně češtiny, alfabeta, azbuka, braille)
-
Spleen 12x24 (916 znaků)
-
Spleen 16x32 (969 znaků)
-
Spleen 32x64 (969 znaků)
-
Tahoma 8 (450 znaků) — font má proměnnou šířku
-
Tahoma 10 (450 znaků) — font má proměnnou šířku
-
Tahoma 12 (348 znaků)
-
Tahoma 16 (348 znaků)



Instalace knihovny
Knihovna ke stažení ssd1306_utf8_lib.tar.gz nebo ssd1306_utf8_lib.zip
cd
wget https://sspvc.lixis.cz/pmp/ssd1306_utf8/ssd1306_utf8_lib.tar.gz
tar xfvz ssd1306_utf8_lib.tar.gz
echo 'export LIB_SSD1306_UTF8_PATH=~/ssd1306_utf8_lib' >>~/.bashrc
source ~/.bashrc
cd
wget https://sspvc.lixis.cz/pmp/ssd1306_utf8/ssd1306_utf8_lib.tar.gz
tar xfvz ssd1306_utf8_lib.tar.gz
echo 'export LIB_SSD1306_UTF8_PATH=~/ssd1306_utf8_lib' >>~/.zprofile
source ~/.zprofile
Použití knihovny
Do adresáře vašeho projektu nakopírute soubor pico_lib_ssd1306_utf8_import.cmake a vložte ho direktivou include do vašeho CMakeLists.txt.
Do target_include_directories přidejte ${ssd1306_utf8_SOURCE_DIR}/src.
Do target_link_libraries přidejte hardware_i2c a ssd1306_utf.
cmake_minimum_required(VERSION 3.13)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(ssd1306_test C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
include(pico_lib_ssd1306_utf8_import.cmake)
add_executable(ssd1306_test
ssd1306_test.c
)
target_include_directories(ssd1306_test PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${ssd1306_utf8_SOURCE_DIR}/src
)
target_link_libraries(ssd1306_test
pico_stdlib
hardware_i2c
ssd1306_utf8
)
pico_enable_stdio_usb(ssd1306_test 1)
pico_enable_stdio_uart(ssd1306_test 0)
pico_add_extra_outputs(ssd1306_test)
CMakeLists.txt se dá udělat elegantněji. Soubor pico_lib_ssd1306_utf8_import.cmake si přečteme přímo z adresáře, kam jsme nainstalovali knihovnu.
Adresář, kde je knihovna, si vezmeme z proměnné prostředí LIB_SSD1306_UTF8_PATH.
cmake_minimum_required(VERSION 3.13)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(ssd1306_test C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
include($ENV{LIB_SSD1306_UTF8_PATH}/pico_lib_ssd1306_utf8_import.cmake)
add_executable(ssd1306_test
ssd1306_test.c
)
target_include_directories(ssd1306_test PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${ssd1306_utf8_SOURCE_DIR}/src
)
target_link_libraries(ssd1306_test
pico_stdlib
hardware_i2c
ssd1306_utf8
)
pico_enable_stdio_usb(ssd1306_test 1)
pico_enable_stdio_uart(ssd1306_test 0)
pico_add_extra_outputs(ssd1306_test)
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#include "font.h"
#include <stdio.h>
#include <string.h>
// pro OLED displej SSD1306
#define DISPLAY_WIDTH 128 // šířka displeje
#define DISPLAY_HEIGHT 32 // výška displeje
#define I2C_ADDRESS 0x3C // i2c adresa
#define I2C_FREQ 1000000 // rychlost i2c sběrnice
// rychlost i2c sběrnice může být až 2000000
#define SDA_PIN 4 // datový pin
#define SDC_PIN 5 // hodinový pin
#define I2C i2c0 // i2c hardware
// struktura pro OLED displej včetně framebufferu
static ssd1306_t disp;
// všechny použité fonty
extern bitmapFONT font_tahoma_10;
extern bitmapFONT font_spleen_16x32;
// nastavení I2C sběrnice
void setup_i2c(void)
{
i2c_init(I2C, I2C_FREQ);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SDC_PIN);
// pauza je nutná kvůli displeji. Pokud není displej se někdy nerozsvítí
sleep_ms(200);
}
void zapnuti_displeje( void )
{
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); // inicializace
ssd1306_poweron(&disp); // zapnutí displeje
ssd1306_clear(&disp); // vymazání displeje
ssd1306_contrast(&disp,0x50);
ssd1306_show(&disp); // zobrazíme na displeji
}
int main()
{
// nastavení displeje SSD1306
setup_i2c();
zapnuti_displeje();
sleep_ms(10);
// vymazání framebufferu
ssd1306_clear(&disp);
// nakreslení obdélníka z horního levého x=0,y=0
// do dolního levého rohu x=127,y=31
ssd1306_draw_empty_square(&disp, 0, 0, 127, 31);
ssd1306_draw_empty_square(&disp, 1, 1, 18, 31);
// řecké písmeno fi fontem spleen 16x32 (horní roh znaku x=3, y=3)
ssd1306_draw_utf8_char_with_font(&disp, 3, 3, &font_spleen_16x32, 421 );
// text fontem spleen 6x12 z bodu x=26, y=2
ssd1306_draw_utf8_string(&disp, 26, 2, &font_tahoma_10, "Maličký ježeček");
// text fontem tahoma 10 z bodu x=26, y=16
ssd1306_draw_utf8_string(&disp, 26, 16, &font_tahoma_10, "žere žlutá jablíčka.");
ssd1306_show(&disp); // zobrazíme písmenka na displeji
// ukončení práce s displejem (uvolnění paměti framebufferu)
ssd1306_deinit(&disp);
}
API knihovny
Datové struktury
typedef struct {
uint8_t width; // šířka dispeje
uint8_t height; // výška displeje
uint8_t pages; // počet stránek displeje (počítá se při inicializaci)
uint8_t address; // i2c adresa displeje
i2c_inst_t *i2c_i; // i2c sběnice (i2c0 nebo i2c1)
bool external_vcc; // zda používá displej napájení podsvitu z vnějšku (obvykle ne)
uint8_t *buffer; // obrazový buffer
size_t bufsize; // velikost obrazového bufferu
} ssd1306_t;
// struktura bitmapového fontu
typedef struct bitmap_font {
unsigned char Width; // maximální šířka znaku
unsigned char Height; // výška znaku
unsigned int Chars; // počet znaků ve fontu
const unsigned char *Widths; // ukazatel na pole šířek jednotlivých znaků
const uint32_t *Index; // pole UTF-8 kódu znaků
const unsigned char *Bitmap; // pole bitmap jednotlivých znaků
} bitmapFONT;
Nastavení a ukončení
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint16_t width -- šířka displeje
// uint16_t height -- výška displeje
// uint8_t address -- I2C adresa displeje (obvykle 0x3c)
// i2c_inst_t * -- ukazatel na instanci I2C sběrnice (buď i2c0 nebo i2c1)
bool ssd1306_init(ssd1306_t *p, uint16_t width, uint16_t height, uint8_t address, i2c_inst_t *i2c_instance);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
void ssd1306_deinit(ssd1306_t *p);
Příklad nastavení displeje a ukončení práce s ním:
-
datový pin SCK displeje je připojen na GPIO5 Pico (I2C0 SCL)
-
hodinový pin SDA displeje je připojen na GPIO4 Pico (I2C0 SDA)
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#include "font.h"
#include <stdio.h>
#include <string.h>
// pro OLED displej SSD1306
#define DISPLAY_WIDTH 128 // šířka displeje
#define DISPLAY_HEIGHT 32 // výška displeje
#define I2C_ADDRESS 0x3C // i2c adresa
#define I2C_FREQ 1000000 // rychlost i2c sběrnice
#define SDA_PIN 4 // datový pin SDA
#define SDC_PIN 5 // hodinový pin SCK
#define I2C i2c0 // i2c hardware
// struktura pro OLED displej včetně framebufferu
static ssd1306_t disp;
int main()
{
// nastavení I2C sběrnice
i2c_init(I2C, I2C_FREQ);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SDC_PIN);
// pauza je nutná kvůli displeji. Pokud není, displej se někdy nerozsvítí
sleep_ms(200);
// nastavení displeje SSD1306
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C);
// ... tady je náš kód
// ukončení práce s displejem
ssd1306_deinit(&disp);
}
Ovládání parametrů displeje
// ssd1306_t *p -- ukazatel na instanci struktury displeje
void ssd1306_poweron(ssd1306_t *p);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
void ssd1306_poweroff(ssd1306_t *p);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint8_t val -- hodnota kontrastu v procentech od 0 (nic není vidět) do 100 (maximální jas)
void ssd1306_contrast(ssd1306_t *p, uint8_t val);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint8_t inv -- je-li inv 0 prohodí se barvy, černý bod se stane bílým a bílý bod se stane černým)
// -- je-li inv nenulový pak displej zobrazuje normálně
void ssd1306_invert(ssd1306_t *p, uint8_t inv);
Grafické funkce
// ssd1306_t *p -- ukazatel na instanci struktury displeje
void ssd1306_show(ssd1306_t *p);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
void ssd1306_clear(ssd1306_t *p);
Tato funkce pouze vynuluje framebuffer. Obraz na displeji se nezmění.
Pokud chceme vymazat obraz na displeji, musíme zavolat potom funkci ssd1306_show():
ssd1306_t disp;
ssd1306_clear(&disp);
ssd1306_show(&disp);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- x souřadnice bodu
// uint32_t y -- y souřadnice bodu
void ssd1306_clear_pixel(ssd1306_t *p, uint32_t x, uint32_t y);
Souřadnice x=0 a y=0 se nachází v levém horním rohu displeje. Pokud se náhodou stane že x>šířka nebo y>výška, neděje se nic.
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- x souřadnice bodu
// uint32_t y -- y souřadnice bodu
void ssd1306_draw_pixel(ssd1306_t *p, uint32_t x, uint32_t y);
Souřadnice x=0 a y=0 se nachází v levém horním rohu displeje. Pokud se náhodou stane že x>šířka nebo y>výška, neděje se nic. Ostatní grafické funkce používají ke kreslení do framebufferu tuto funkci, proto grafické objekty nemohou být rozměrově mimo displej (jsou oříznuty).
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// int32_t x1 -- souřadnice x počátečního bodu úsečky
// int32_t y1 -- souřadnice y počátečního bodu úsečky
// int32_t x2 -- souřadnice x koncového bodu úsečky
// int32_t y2 -- současnice y koncového bodu úsečky
void ssd1306_draw_line(ssd1306_t *p, int32_t x1, int32_t y1, int32_t x2, int32_t y2);
Pokud jsou souřadnice některého bodu úsečky mimo rozsah displeje, nebudou nakresleny.
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- souřadnice x levého horního rohu obdélníka
// uint32_t y -- souřadnice y levého horního rohu obdélníka
// int32_t width -- šířka obdélníka
// int32_t width -- výška obdélníka
void ssd1306_clear_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- souřadnice x levého horního rohu obdélníka
// uint32_t y -- souřadnice y levého horního rohu obdélníka
// int32_t width -- šířka obdélníka
// int32_t width -- výška obdélníka
void ssd1306_draw_empty_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- souřadnice x levého horního rohu obdélníka
// uint32_t y -- souřadnice y levého horního rohu obdélníka
// int32_t width -- šířka obdélníka
// int32_t width -- výška obdélníka
void ssd1306_draw_square(ssd1306_t *p, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t x -- souřadnice x levého horního rohu obdélníka kam bude umístěn znak
// uint32_t y -- souřadnice y levého horního rohu obdélníka kam bude umístěn znak
// bitmapFONT *Font -- ukazatel na strukturu fontu
// uint16_t Index -- index v poli znaků
// funkce vrací šířku obdélníka v bodech, který ohraničuje daný znak
uint16_t ssd1306_draw_utf8_char_with_font(ssd1306_t *p, uint32_t x, uint32_t y, bitmapFONT *Font, uint16_t Index );
// ssd1306_t *p -- ukazatel na instanci struktury displeje
// uint32_t Xstart -- souřadnice x levého horního rohu obdélníka kam bude umístěn řetezec znaků
// uint32_t Ystart -- souřadnice y levého horního rohu obdélníka kam bude umístěn řetezec znaků
// bitmapFONT *Font -- ukazatel na strukturu fontu
// const char *pString -- ukazatel na řetezec znaků
// funkce vrací šířku obdélníka v bodech, který ohraničuje daný řetezec
uint16_t ssd1306_draw_utf8_string(ssd1306_t *p, uint32_t Xstart, uint32_t Ystart, bitmapFONT *Font, const char *pString );
Pokud se řetezec nevejde šířkou na displej, je zalomen na další řádek.
Příklady
Obdélníky
Kreslení prázdného obdélníka a plného obdélníka.

cmake_minimum_required(VERSION 3.13)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(obdelnik C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
include($ENV{LIB_SSD1306_UTF8_PATH}/pico_lib_ssd1306_utf8_import.cmake)
add_executable(obdelnik
obdelnik.c
)
target_include_directories(obdelnik PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${ssd1306_utf8_SOURCE_DIR}/src
)
target_link_libraries(obdelnik
pico_stdlib
hardware_i2c
ssd1306_utf8
)
pico_enable_stdio_usb(obdelnik 1)
pico_enable_stdio_uart(obdelnik 0)
pico_add_extra_outputs(obdelnik)
/* obdelnik.c
* Příklad kreslení obdélníka na OLED displeji ssd1306
* (c) Jirka Chráska 2026, <jirka@lixis.cz>
*
*/
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#include "font.h"
#include <stdio.h>
#include <string.h>
// pro OLED displej SSD1306
#define DISPLAY_WIDTH 128 // šířka displeje
#define DISPLAY_HEIGHT 32 // výška displeje
#define I2C_ADDRESS 0x3C // i2c adresa
#define I2C_FREQ 100000 // rychlost i2c sběrnice
// rychlost i2c sběrnice může být až 2000000
#define SDA_PIN 4 // datový pin
#define SDC_PIN 5 // hodinový pin
#define I2C i2c0 // i2c hardware
// struktura pro OLED displej včetně framebufferu
static ssd1306_t disp;
// nastavení I2C sběrnice
void setup_i2c(void)
{
i2c_init(I2C, I2C_FREQ);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SDC_PIN);
// pauza je nutná kvůli displeji. Pokud není displej se někdy nerozsvítí
sleep_ms(200);
}
void zapnuti_displeje( void )
{
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); // inicializace
ssd1306_poweron(&disp); // zapnutí displeje
ssd1306_clear(&disp); // vymazání displeje
ssd1306_contrast(&disp,0x50);
ssd1306_show(&disp); // zobrazíme na displeji
}
int main()
{
// nastavení displeje SSD1306
setup_i2c();
zapnuti_displeje();
sleep_ms(10);
// vymazání framebufferu
ssd1306_clear(&disp);
// nakreslení obdélníka z horního levého x=0,y=0
// do dolního levého rohu x=127,y=31
ssd1306_draw_empty_square(&disp, 0, 0, 127, 31);
// nakreslení plného obdélníka
ssd1306_draw_square(&disp, 100, 0, 128, 31);
ssd1306_show(&disp); // zobrazíme na displeji
sleep_ms(10000);
// ukončení práce s displejem (uvolnění paměti framebufferu)
ssd1306_deinit(&disp);
}
Kreslení pohyblivého obdélníku
/* obdelnik.c
* Příklad kreslení obdélníka na OLED displeji ssd1306
* (c) Jirka Chráska 2026, <jirka@lixis.cz>
*
*/
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#include "font.h"
// pro OLED displej SSD1306
#define DISPLAY_WIDTH 128 // šířka displeje
#define DISPLAY_HEIGHT 32 // výška displeje
#define I2C_ADDRESS 0x3C // i2c adresa
#define I2C_FREQ 1000000 // rychlost i2c sběrnice
// rychlost i2c sběrnice může být až 2000000
#define SDA_PIN 4 // datový pin
#define SDC_PIN 5 // hodinový pin
#define I2C i2c0 // i2c hardware
// struktura pro OLED displej včetně framebufferu
static ssd1306_t disp;
// nastavení I2C sběrnice
void setup_i2c(void)
{
i2c_init(I2C, I2C_FREQ);
gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(SDC_PIN, GPIO_FUNC_I2C);
gpio_pull_up(SDA_PIN);
gpio_pull_up(SDC_PIN);
// pauza je nutná kvůli displeji. Pokud není displej se někdy nerozsvítí
sleep_ms(200);
}
void zapnuti_displeje( void )
{
ssd1306_init(&disp, DISPLAY_WIDTH, DISPLAY_HEIGHT, I2C_ADDRESS, I2C); // inicializace
ssd1306_poweron(&disp); // zapnutí displeje
ssd1306_clear(&disp); // vymazání displeje
ssd1306_contrast(&disp,0x50);
ssd1306_show(&disp); // zobrazíme na displeji
}
int main()
{
// nastavení displeje SSD1306
setup_i2c();
zapnuti_displeje();
sleep_ms(2000);
// vymazání framebufferu
ssd1306_clear(&disp);
// nakreslení obdélníka z horního levého x=0,y=0
// do dolního levého rohu x=127,y=31
ssd1306_draw_empty_square(&disp, 0, 0, 127, 31);
// nakreslení plného obdélníka
//ssd1306_draw_square(&disp, 100, 0, 128, 31);
ssd1306_show(&disp); // zobrazíme na displeji
sleep_ms(1000);
for( int i=0; i<127; i++) {
// kreslení úsečky
ssd1306_draw_line(&disp, 127-i, 1, 127-i, 30);
ssd1306_show(&disp);
sleep_ms(50);
}
sleep_ms(1000);
for( int i=0; i<127; i++) {
// vymazání obdélníka
ssd1306_clear_square(&disp, 1, 1, i, 30);
ssd1306_show(&disp);
sleep_ms(50);
}
sleep_ms(5000);
ssd1306_poweroff(&disp);
// ukončení práce s displejem (uvolnění paměti framebufferu)
ssd1306_deinit(&disp);
}
Zdroje a odkazy
https://github.com/zahash/utf8.c C knihovna pro práci s UTF-8