На этом уроке мы разберёмся с подключением OLED дисплея к микроконтроллеру из семейства STM32. Для эксперимента используем отладочную плату на STM32F030F4P6, хотя на месте этого МК может быть любой другой STM32.
Подключать будем достаточно распространённый дисплей OLED, с контроллером SSD1306 и разрешением 128 x 32 точки.
Соединяем эти два устройство шиной I2C. Хотя в данном примере мы использовали QIIC разъёмы (подробнее о QIIC), в действительности можно использовать любую другую плату и соединить их хоть пайкой. Главное соблюдать принцип подключения по шине I2C.
Оба использованных в данном уроке устройства можно приобрести у нас в магазине:
Настройка выводов
Создаём новый проект в STM32CubeIDE и выбираем подходящую модель микроконтроллера. В данном примере использовался STM32F030F4P6.
Затем, открываем экран Pinout & Configuration, далее раздел Connectivity. Выбираем там любой доступный I2C и в настройках параметр Mode устанавливаем в значение I2C.
Программа
Чтобы не писать код управления дисплеем с нуля, используем готовую библиотеку, в которой реализовано общение с контроллером дисплея SSD1306. Ссылка на исходный код в конце статьи.
О том как настроить среду для работы с библиотеками можно узнать из урока.
Переходим к коду файла main.c. Подключим библиотеку, добавив соответствующую директиву в начале программы:
/* USER CODE BEGIN Includes */
#include "ssd1306.h"
/* USER CODE END Includes */
И чуть ниже вставим код для вывода текста на дисплей.
/* USER CODE BEGIN 2 */
ssd1306_Init();
ssd1306_Fill(Black);
ssd1306_SetCursor(5, 10);
ssd1306_WriteString("Hello world!", Font_11x18, White);
ssd1306_UpdateScreen();
/* USER CODE END 2 */
Готово. Загружаем программу на микроконтроллер и наблюдаем:
В рассматриваемой библиотеке есть все основные функции для создания графики. Описание этих функций можно подсмотреть в файле ssd1306.h. Вот некоторые из них:
ssd1306_Fill — заливка экрана одним цветом
ssd1306_DrawPixel — отрисовка точки
ssd1306_Line — отрисовка линии по алгоритму Брезенхэма
ssd1306_WriteString
ssd1306_Line — отрисовка лигии по алгоритму Брезенхэма
ssd1306_DrawCircle — окружность
ssd1306_DrawRectangle — прямоугольник
ssd1306_DrawBitmap — изображение
Собственно, остановимся на последней функции. Выведем на экран логотип RobotClass.
Вывод изображения на OLED
Для начала, как и в предыдущих примерах для работы с дисплеями (OLED 0.96, Nokia5110) мы подготовим изображение. Преобразуем его в массив.
Разрешение нашего дисплея — 128 x 32 точки. Следовательно, обрезаем и масштабируем картинку ровно под этот размер и сохраняем в формате BMP в режиме 256 цветов на точку. При этом сама картинка должна быть монохромной, без градаций серого.
Есть в вашем конкретном редакторе не получается сохранить файл в таком формате, можно открыть его в обычном Paint и сохранить там.
Затем, открываем наш инструмент для конвертирования картинок в массив:
https://tools.robotclass.ru/bmp2bin/bmp2bin.html
Загружаем файл, и жмём «Конвертировать». Настройки можно не трогать. Полученный массив вставляем в нашу программу:
/* USER CODE BEGIN PV */
const uint8_t logo [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0xfc, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xf0, 0x3e, 0x00, 0xf0, 0xfc, 0x03, 0xf0, 0xff, 0x81, 0xc0, 0x00, 0x00, 0x0c, 0x07, 0x00,
0x03, 0xfc, 0xfc, 0x00, 0xfc, 0xfe, 0x0f, 0xf8, 0xff, 0x87, 0xf7, 0x00, 0x70, 0x3f, 0x1f, 0x80,
0x03, 0x9e, 0xfc, 0x00, 0xfc, 0xc7, 0x1e, 0x3c, 0x1c, 0x0f, 0xf7, 0x00, 0xf0, 0x7f, 0x3f, 0x80,
0x03, 0x8e, 0xfc, 0x00, 0x7c, 0xc7, 0x3c, 0x1e, 0x1c, 0x1c, 0x17, 0x00, 0xf8, 0x71, 0x38, 0x00,
0x03, 0x8e, 0xfc, 0x00, 0xfc, 0xc7, 0x38, 0x0e, 0x1c, 0x38, 0x07, 0x01, 0xf8, 0x70, 0x38, 0x00,
0x03, 0xfc, 0xfc, 0x00, 0xfc, 0xfe, 0x38, 0x0e, 0x1c, 0x38, 0x07, 0x01, 0xf8, 0x78, 0x3e, 0x00,
0x03, 0xf8, 0x3e, 0x00, 0xf0, 0xfe, 0x38, 0x0e, 0x1c, 0x38, 0x07, 0x01, 0xdc, 0x3e, 0x1f, 0x80,
0x03, 0xf0, 0x1f, 0x03, 0xe0, 0xff, 0x38, 0x0e, 0x1c, 0x38, 0x07, 0x03, 0xfc, 0x1f, 0x0f, 0xc0,
0x03, 0xf8, 0x1f, 0xc7, 0xf0, 0xc3, 0xb8, 0x0e, 0x1c, 0x38, 0x07, 0x03, 0xfe, 0x07, 0x81, 0xc0,
0x03, 0xb8, 0x3f, 0xff, 0xf0, 0xc3, 0xbc, 0x0e, 0x1c, 0x3c, 0x07, 0x07, 0xfe, 0x03, 0xa1, 0xc0,
0x03, 0x9c, 0x1f, 0xff, 0xe0, 0xc7, 0x9e, 0x1c, 0x1c, 0x1e, 0x37, 0x07, 0x0e, 0x63, 0xb1, 0xc0,
0x03, 0x8e, 0x0d, 0xff, 0xc0, 0xff, 0x0f, 0xfc, 0x1c, 0x0f, 0xf7, 0xf7, 0x07, 0x7f, 0x3f, 0xc0,
0x03, 0x8f, 0x00, 0x78, 0x00, 0xfe, 0x07, 0xf0, 0x1c, 0x07, 0xf7, 0xfe, 0x07, 0x7e, 0x3f, 0x80,
0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* USER CODE END PV */
Предыдущий код можно не удалять. Лучше оформим его в виде функции для последующего использования.
Для этого объявим две функции, старую для отрисовки текста и новую для изображения:
/* USER CODE BEGIN PFP */
void displayDrawBitmap();
void displayDrawText();
/* USER CODE END PFP */
А затем реализации для них:
/* USER CODE BEGIN 4 */
void displayDrawBitmap(){
ssd1306_Fill(Black);
ssd1306_DrawBitmap(0, 0, logo, 128, 32, White);
ssd1306_UpdateScreen();
}
void displayDrawText(){
ssd1306_Fill(Black);
ssd1306_SetCursor(5, 10);
ssd1306_WriteString("Hello world!", Font_11x18, White);
ssd1306_UpdateScreen();
}
/* USER CODE END 4 */
Теперь в суперцикле добавим вызовы этих функций через паузу в 3 секунды.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
displayDrawText();
HAL_Delay(3000);
displayDrawBitmap();
HAL_Delay(3000);
}
/* USER CODE END 3 */
Готово. Загружаем на STM32 и смотрим.