Читатель нашего блога Михаил (mishadesh) создал отличную библиотеку для STM32 для работы с LCD дисплеем и предложил написать статью для демонстрации ее возможностей. Собственно, сегодня именно об этом и пойдет речь - разберем, какие реализованы функции, а также в конце статьи будет выложен пример для работы с дисплеем.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также небольшая подборка на смежную тему из нового курса:
- Подключение дисплея на базе ST7735 к микроконтроллеру STM32.
- Дисплей на базе ST7735 и STM32. Вывод изображения.
- Дисплей на базе контроллера SSD1306. Библиотека для STM32.
- STM32 и семисегментный индикатор. Динамическая индикация.
Как обычно начнем с обсуждения железа... А тут на самом деле и не о чем говорить. Как и в первой статье, посвященной работе с дисплеями (ссылка), мы будем использовать отладочную плату Mini-STM32. Собственно, подключение дисплея, основные команды для записи данных, последовательность инструкций для инициализации - все это там есть. Поэтому сейчас переходим сразу к обсуждению библиотеки. Вот полный список функций с пояснениями:
void LCD_PutPixel(uint16_t x, uint16_t y, uint16_t color);
Функция принимает 3 аргумента - координаты точки (x и y), а также цвет и меняет цвет пикселя, расположенного по указанным координатам.
void LCD_SetOrient(TOrientation orientation);
Следующая функция, как видно из ее названия, меняет ориентацию экрана. Возможно два положения экрана, соответственно два возможных значения параметра orientation:
- Orientation_Portrait
- Orientation_Album
Идем дальше:
uint16_t LCD_GetMaxX(void); uint16_t LCD_GetMaxY(void);
Две похожие функции - одна возвращает максимальное значение координаты по оси x, другая - по оси y. Функции учитывают текущее положение экрана. Переходим к функциям рисования, и первая на очереди:
uint8_t LCD_DrawChar(uint16_t x, uint16_t y, uint8_t c, uint16_t textColor, uint16_t backColor, uint8_t isTransparent);
Функция отрисовывает на графическом дисплее символ, располагая его по переданным в функцию координатам, а также задавая его цвет. Начертание символа соответствует шрифту, определенному в файле font.c (файл идет в составе библиотеки). Из функции LCD_DrawChar() плавно вытекает следующая функция:
void LCD_DrawString(char* s, uint16_t x, uint16_t y, uint16_t color, uint16_t backColor, uint8_t isTransparent);
Тут понятно и без лишних слов ) Функция печатает на дисплее строку текста. Базой для этой функции является предыдущая - LCD_DrawChar(). Помимо символов и текста, конечно же, необходимо иметь возможность нарисовать основные графические примитивы, например линию или круг. Для этого реализовано следующее:
void LCD_drawLine(int x1, int y1, int x2, int y2, uint16_t color); void LCD_DrawRect(int x1, int y1, int x2, int y2, uint16_t color, uint8_t filled); void LCD_DrawEllipse(uint16_t X1, uint16_t Y1, uint16_t R, uint16_t color);
Чтобы нарисовать линию, нужно передать в функцию координаты начальной точки, координаты конечной точки, а также нужный цвет. А для прямоугольника - координаты верхнего левого угла и координаты правого нижнего угла (!). Последний параметр filled - определяет, необходимо ли выполнять заливку фигуры. Единица - значит да, фигура будет закрашена выбранным цветом, ноль - будет нарисован только контур фигуры. С этим понятно, осталась только окружность - функция DrawEllipse(). Здесь вместо координат начала и конца (верхнего/нижнего углов) передаем в качестве аргументов центр окружности и радиус.
Ну и напоследок еще одна функция:
void LCD_FillScr(uint16_t color);
Функция позволяет залить экран сплошным цветом. Все перечисленные функции реализованы в файле GUI_DRV.c. Помимо них библиотека включает в себя функции для записи данных в дисплей (LCD_DRIVER.c) а также уже упомянутые шрифты (font.c). Как видите, все четко отсортировано по разным файлам, так что, в принципе, все очень понятно, поэтому давайте перейдем к практическому примеру. И вот ссылка на полный проект с примером - LCD Example.
Давайте разбираться! Идем в файл main.c. Не буду приводить полный код функций инициализации периферии и дисплея, все это можно посмотреть непосредственно в файле, либо в предыдущей статье, ссылка на которую была в начале этой статьи. Функция main():
int main(void) { initPeriph(); initFSMC(); initLCD(); delay(10000); LCD_FillScr(0xFFFF); delay(100); LCD_SetOrient(Orientation_Album); delay(100); LCD_DrawString("Библиотека для LGDP4532",30,30,0x888F,0x0000,0); LCD_DrawRect(100,100,200,200,0x0000,0); LCD_DrawRect(120,120,180,180,0xFF00,1); LCD_DrawEllipse(150,150,50,0xF000); while(1) { } }
Начинаем с инициализации, закрашиваем экран белым цветом и устанавливаем альбомную ориентацию экрана. И теперь переходим к отрисовке графики. Выводим на экран строку, а также два прямоугольника и круг. Результат налицо:
Очевидно, что все работает отлично )
Итак, на этом на сегодня заканчиваем, огромное спасибо Михаилу за проделанную работу и приведенные материалы. Вот контакты автора библиотеки:
- Skype - mishadesh
- E-Mail - mishadesh@gmail.com
На этом все, спасибо за внимание, до скорых встреч!
А как вывести на экран целочисленную переменную?
отрисовать?
Знаки на дисплей выводятся как битмап-изображения.
К каждому ASCII карактеру привязывается массив с закодированой картинкой, после пишутся функции вывода, по очереди отрисовывающие битмапы слева направо... Ну или как там у вас, а то тусил как-то на иранском форуме... 😀
Вопрос? При подключении сенсора там 4 пина к периферии,
выводы ставить Pin GPIO_Output или их нужно подтянуть к питанию (как пользовательскую кнопку) а выводы ставить Pin GPIO_Input чтобы регистрировать нажатие на сенсор?
Добрый день!
А какой дисплей?
Добрый день! Почему при практической реализации функции окружности с радиусом более 30 пикселей окружность превращается в две дуги? (разрыв окружности происходит по вертикали)...
Добрый день!
Попробуй автору библиотеки на почту написать, но времени много прошло, я так чувствую, что шансы не так велики...