Передмова
![]() |
| OLED Display 0.96'' SSD1306 |
CubeMX for STM32
- RCC - Crystal/Ceramic resonator
- SYS - Serial Wire
- обираємо порт I2C до якого буде підключено дисплей, я обрав I2C1
![]() |
| Налаштування в шпильок |
![]() |
| Наалаштування тактування |
![]() |
| Налаштування I2C для STM32F030F4 |
Підключення бібліотеки до проекту та демо-код
- fonts.h - заголовний файл для трьох шрифтів
- ssd1306_defines.h - налаштування для роботи дисплею
- ssd1306.h - заголовний файл бібліотеки
- font.c - три шрифта розміром 7х10, 11х18, 16х26
- ssd1306.c - сирцевий файл бібліотеки
- image.h - заголовний файл зображення для демки
Відкриємо в засобі розробки файл ssd1306_defines.h і налаштуємо бібліотеку для правильної роботи з дисплеєм:
- //#define USE_DMA - коли I2C шина для передачі використовує DMA потрібно розкоментувати рядок
- #define STM32_I2C_PORT hi2c1 - вказати порт I2C до якого під'єднано дисплей
- #define SSD1306_ADDRESS 0x3C - адреса дисплею на шині I2C
- #define SSD1306_128X64 - тип дисплею 128Х64 або 128Х32
Тепер напишемо демо програмку, щоб оцінити роботу дисплею. Відкриваємо файл "main.c" в засобі розробки і в визначених програмою CubeMX місцях для користувача, напишемо такий код:
- Вкладемо заголовний файл з бібліотекою до нашого коду та файл з зображенням:
/* USER CODE BEGIN Includes */ #include "ssd1306.h"
#include "image.h"
/* USER CODE END Includes */
- Напишемо декілька функцій для демонстрації можливостей бібліотеки
/* USER CODE BEGIN 0 */ // Adapted from Adafruit_SSD1306 void drawLines() { for (int16_t i = 0; i < ssd1306_GetWidth(); i += 4) { ssd1306_DrawLine(0, 0, i, ssd1306_GetHeight() - 1); ssd1306_UpdateScreen(); HAL_Delay(10); } for (int16_t i = 0; i < ssd1306_GetHeight(); i += 4) { ssd1306_DrawLine(0, 0, ssd1306_GetWidth() - 1, i); ssd1306_UpdateScreen(); HAL_Delay(10); } HAL_Delay(250); ssd1306_Clear(); for (int16_t i = 0; i < ssd1306_GetWidth(); i += 4) { ssd1306_DrawLine(0, ssd1306_GetHeight() - 1, i, 0); ssd1306_UpdateScreen(); HAL_Delay(10); } for (int16_t i = ssd1306_GetHeight() - 1; i >= 0; i -= 4) { ssd1306_DrawLine(0, ssd1306_GetHeight() - 1, ssd1306_GetWidth() - 1, i); ssd1306_UpdateScreen(); HAL_Delay(10); } HAL_Delay(250); ssd1306_Clear(); for (int16_t i = ssd1306_GetWidth() - 1; i >= 0; i -= 4) { ssd1306_DrawLine(ssd1306_GetWidth() - 1, ssd1306_GetHeight() - 1, i, 0); ssd1306_UpdateScreen(); HAL_Delay(10); } for (int16_t i = ssd1306_GetHeight() - 1; i >= 0; i -= 4) { ssd1306_DrawLine(ssd1306_GetWidth() - 1, ssd1306_GetHeight() - 1, 0, i); ssd1306_UpdateScreen(); HAL_Delay(10); } HAL_Delay(250); ssd1306_Clear(); for (int16_t i = 0; i < ssd1306_GetHeight(); i += 4) { ssd1306_DrawLine(ssd1306_GetWidth() - 1, 0, 0, i); ssd1306_UpdateScreen(); HAL_Delay(10); } for (int16_t i = 0; i < ssd1306_GetWidth(); i += 4) { ssd1306_DrawLine(ssd1306_GetWidth() - 1, 0, i, ssd1306_GetHeight() - 1); ssd1306_UpdateScreen(); HAL_Delay(10); } HAL_Delay(250); } // Adapted from Adafruit_SSD1306 void drawRect(void) { for (int16_t i = 0; i < ssd1306_GetHeight() / 2; i += 2) { ssd1306_DrawRect(i, i, ssd1306_GetWidth() - 2 * i, ssd1306_GetHeight() - 2 * i); ssd1306_UpdateScreen(); HAL_Delay(10); } } // Adapted from Adafruit_SSD1306 void fillRect(void) { uint8_t color = 1; for (int16_t i = 0; i < ssd1306_GetHeight() / 2; i += 3) { ssd1306_SetColor((color % 2 == 0) ? Black : White); // alternate colors ssd1306_FillRect(i, i, ssd1306_GetWidth() - i * 2, ssd1306_GetHeight() - i * 2); ssd1306_UpdateScreen(); HAL_Delay(10); color++; } // Reset back to WHITE ssd1306_SetColor(White); } // Adapted from Adafruit_SSD1306 void drawCircle(void) { for (int16_t i = 0; i < ssd1306_GetHeight(); i += 2) { ssd1306_DrawCircle(ssd1306_GetWidth() / 2, ssd1306_GetHeight() / 2, i); ssd1306_UpdateScreen(); HAL_Delay(10); } HAL_Delay(1000); ssd1306_Clear(); // This will draw the part of the circel in quadrant 1 // Quadrants are numberd like this: // 0010 | 0001 // ------|----- // 0100 | 1000 // ssd1306_DrawCircleQuads(ssd1306_GetWidth() / 2, ssd1306_GetHeight() / 2, ssd1306_GetHeight() / 4, 0b00000001); ssd1306_UpdateScreen(); HAL_Delay(200); ssd1306_DrawCircleQuads(ssd1306_GetWidth() / 2, ssd1306_GetHeight() / 2, ssd1306_GetHeight() / 4, 0b00000011); ssd1306_UpdateScreen(); HAL_Delay(200); ssd1306_DrawCircleQuads(ssd1306_GetWidth() / 2, ssd1306_GetHeight() / 2, ssd1306_GetHeight() / 4, 0b00000111); ssd1306_UpdateScreen(); HAL_Delay(200); ssd1306_DrawCircleQuads(ssd1306_GetWidth() / 2, ssd1306_GetHeight() / 2, ssd1306_GetHeight() / 4, 0b00001111); ssd1306_UpdateScreen(); } void drawProgressBarDemo(int counter) { char str[128]; // draw the progress bar ssd1306_DrawProgressBar(0, 32, 120, 10, counter); // draw the percentage as String ssd1306_SetCursor(64, 15); sprintf(str, "%i%%", counter); ssd1306_WriteString(str, Font_7x10); ssd1306_UpdateScreen(); } /* USER CODE END 0 */
- Зробимо ініціалізацію дисплею, встановимо орієнтацію дисплею, очистимо і встановимо білий колір:
/* USER CODE BEGIN 2 */ ssd1306_Init(); ssd1306_FlipScreenVertically(); ssd1306_Clear(); ssd1306_SetColor(White); /* USER CODE END 2 */
- В циклі викликаємо по черзі функції для демонстрації:
/* USER CODE BEGIN WHILE */ while (1) { drawLines(); HAL_Delay(1000); ssd1306_Clear(); drawRect(); HAL_Delay(1000); ssd1306_Clear(); fillRect(); HAL_Delay(1000); ssd1306_Clear(); drawCircle(); HAL_Delay(1000); ssd1306_Clear(); for(int i = 0; i < 100; i++) { drawProgressBarDemo(i); HAL_Delay(25); ssd1306_Clear(); } ssd1306_DrawRect(0, 0, ssd1306_GetWidth(), ssd1306_GetHeight()); ssd1306_SetCursor(8, 20); ssd1306_WriteString("SSD1306", Font_16x26); ssd1306_UpdateScreen(); HAL_Delay(2000); ssd1306_Clear(); ssd1306_DrawBitmap(0, 0, 128, 64, stm32fan); ssd1306_UpdateScreen(); HAL_Delay(2000); ssd1306_InvertDisplay(); HAL_Delay(2000); ssd1306_NormalDisplay(); ssd1306_Clear(); /* USER CODE END WHILE */
- Тепер можна компілювати, заливати до мікроконтролера та милуватись роботою дисплею
Список функцій бібліотеки
uint16_t ssd1306_GetWidth(void); // повертає ширину екрану в пікселях uint16_t ssd1306_GetHeight(void); // повертає висоту екрану в пікселях SSD1306_COLOR ssd1306_GetColor(void); // повертає поточний колір void ssd1306_SetColor(SSD1306_COLOR color); // задаємо поточний колір uint8_t ssd1306_Init(void); // початкова ініціалізація дисплею void ssd1306_Fill(); // заповнення екрану поточним кольором, аналог функції clear void ssd1306_UpdateScreen(void); // оновлення зображення екрану void ssd1306_DrawPixel(uint8_t x, uint8_t y); // малювання пікселю в заданих координатах void ssd1306_DrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); // малювання лінії по заданих координатах void ssd1306_DrawVerticalLine(int16_t x, int16_t y, int16_t length); // малювання вертикальної лінії по заданих координатах void ssd1306_DrawHorizontalLine(int16_t x, int16_t y, int16_t length); // малювання горизонтальної лінії по заданих координатах void ssd1306_DrawRect(int16_t x, int16_t y, int16_t width, int16_t height); // малювання прямокутника по заданих координатах void ssd1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3); // малювання трьохкутника по заданим координатах void ssd1306_FillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height); // малювання зафарбованого прямокутника по заданим координатам void ssd1306_DrawCircle(int16_t x0, int16_t y0, int16_t radius); // малювання кола по заданим координатам void ssd1306_FillCircle(int16_t x0, int16_t y0, int16_t radius); // малювання зафарбованого кола по заданим координатам void ssd1306_DrawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads); // малювання сектора кола по заданим координатам void ssd1306_DrawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress); // малювання прогресбару по заданим координатам і наскільки заповнений у відсотках void ssd1306_DrawBitmap(uint8_t X, uint8_t Y, uint8_t W, uint8_t H, const uint8_t* pBMP); // вивід зображення char ssd1306_WriteChar(char ch, FontDef Font); // друк окремого символу char ssd1306_WriteString(char* str, FontDef Font); // друк текстового рядку void ssd1306_SetCursor(uint8_t x, uint8_t y); // встановлення координат курсору в пікселях void ssd1306_DisplayOn(void); // увімкнути дисплей void ssd1306_DisplayOff(void); // вимкнути дисплей void ssd1306_InvertDisplay(void); // інверсія дисплею void ssd1306_NormalDisplay(void); // нормалізація дисплею void ssd1306_ResetOrientation(void); // скидання оріентації дисплею void ssd1306_FlipScreenVertically(void); // перегорнути зображення дисплею по вертикалі void ssd1306_MirrorScreen(void); // дзеркалювання зображення дисплею void ssd1306_Clear(void); // очистка буферу дисплея
Робота бібліотеки з DMA
![]() |
| Увімкнення режиму DMA |
- Відкриваємо вкладку з налаштуваннями шини I2C
- Режим I2C
- Вкладка DMA Setting
- Кнопка ADD
- Обираємо I2C2_TX (по шині I2C ми тільки відправляємо байти TX, на прийом RX не вмикаємо режим DMA)
![]() |
| Вмикаємо переривання |
Image2CPP
Архів з бібліотекою і демо-кодом
Ланка на драйвер на GitHub








