На этом уроке будем разбираться с тем, как отобразить на популярном среди DIY-энтузиастов OLED дисплее с контроллером SSD1306 русский текст, да ещё и с использование красивых шрифтов.
Список необходимых компонентов
Для выполнения всех экспериментов в этой инструкции потребуются: отладочная плата с микроконтроллером STM32F103C8T6, дисплей OLED и кабель QIIC для удобного подключения по I2C.
Библиотека stm32-ssd1306
Используем известную библиотеку для работы с SSD1306 на stm32. У RobotClass есть своя редакция этой библиотеки, с некоторыми доработками (ссылка в конце).
Далее создаём в STM32CubeIDE новый проект, настраиваем периферию для работы с OLED через I2C интерфейс, а также подключаем библиотеку.
Создание шрифта
Как известно, True Type шрифты являются векторными. Чтобы их эффективно использовать на stm32 придётся их растеризовать в заданном размере. По сути, превратить каждую букву в привычный набор точек. Сделать это можно при помощи python-скрипта, который есть в той же библиотеке.
Устанавливаем python версии 3.9. Готовим файлик нужного нам шрифта, например: nasalization.ttf. И запускаем скрипт generate.py из папки: stm32-ssd1306-master\examples\custom-fonts
c:\Python39\python.exe ./generate.py --font nasalization.ttf --size 16 --atlas atlas.png --charset cp1251 --proportional
- size — отвечает за высоту буквы шрифта, но не в пикселах.
- atlas — указывает на необходимость изображения таблицы символов по окончании процедуры растеризации
- charset — задаёт нужную кодировку
- proportional — делает шрифт не моноширинным (когда каждый символ имеет одинаковую ширину), а пропорциональным.
По завершении работы скрипта мы получим два файла:
- файл с кодами символов — font.c
- изображением символов — atlas.png
Последний нужен сугубо для визуального контроля нашего творения. Если открыть файл font.c, то мы увидим, что символы шрифта получились размером 24×20 точек, а совсем не 16, как мы указывали в генераторе:
static const uint16_t Font24x20 [] = {
...
Также отметим, что у моноширинного шрифта все символы будут иметь размер 24×20, а вот у пропорционального (который мы и сделали) символы будут иметь разный размер: символ ! будет сильно уже, чем русская буква Щ. В случае такого «растопыристого» шрифта как nasalization пропорциональный вариант смотрится гораздо лучше моноширинного.
Теперь копируем этот файл в папку SSD1306/src нашего проекта. Если планируется использовать несколько шрифтов, то файлу лучше дать уникальное имя, например: font_24x20p.c
Готово! Теперь шрифтом можно пользоваться.
Настройка проекта
Есть ещё один момент, который может помешать в покорении кириллицы. Нужно настроить проект таким образом, чтобы он переводил русский текст в IDE, написанный в кодировке UTF8 в текст CP1251 при компиляции.
Заходим в настройки проекта. Далее в раздел C/C++ Build. Первая вкладка Tool Settings, а в ней выбираем пункт MCU GCC Compiler / Miscellaneous. Добавляем флаги компиляции:
-finput-charset=UTF-8 -fexec-charset=cp1251
Сохраняем настройки. Готово, приступаем к программе.
Программа
Пусть на дисплей выводится строка — СТАРТ. Объявим её как указатель на массив char. Далее подключим наш шрифт.
/* USER CODE BEGIN PV */
char* text_cyr = "СТАРТ";
extern const SSD1306_Font_t Font_24x20;
/* USER CODE END PV */
Далее в коде, перед запуском суперцикла проведем инициализацию дисплея командой ssd1306_Init. Затем выводим нужные строки в конкретных координатах. Указываем нужный шрифт.
/* USER CODE BEGIN 2 */
ssd1306_Init();
ssd1306_Fill(Black);
ssd1306_SetCursor(35, 30);
ssd1306_WriteString(text_cyr, Font_24x20, White);
ssd1306_UpdateScreen();
/* USER CODE END 2 */
Загружаем программу на STM32 и смотрим что получилось.
Размышления
Надо понимать, что шрифт с кириллицей занимает в 2 раза больше места, чем без оной. Если ещё использовать большие размеры шрифтов, то можно легко столкнуться с нехваткой места во флеш памяти микроконтроллера. А что если в программе требуется отобразить всего несколько слов большими буквами?
В библиотеке stm32_ssd1306 для этих целей есть возможность растеризовать не отдельные символы, а целый текст. В результате такой операции мы получим массив точек, который останется вывести на экране в нужном месте.
Для этого используем python-скрипт generate.py:
./generate.py --font nasalization.ttf --size 16 --string "СТАРТ"
В результате работы скрипта получим файл string.c с таким содержимым:
const unsigned char string_55x12 [] = {
...
Далее в программе мы можем отобразить это изображение с помощью функции ssd1306_DrawBitmap:
ssd1306_DrawBitmap(35, 30, string_55x12, 55, 12, White);
Полезные ссылки
Библиотека stm32_ssd1306 в репозитории github: