Совсем недавно мы познакомились с работой FSMC в STM32, подключили дисплей и раскрасили его разными цветами (вот). И пока еще не забыли все, что обсуждали в прошлой статье, давайте выведем на дисплей, что-нибудь поинтереснее, а именно какую-нибудь картинку.
Что же нам для этого понадобится?
Ну во-первых сама картинка. Находим какое-нибудь изображение размером 320*240. Я секунд за 20 нагуглил подходящую картинку — кадр из фильма Железный Человек, реклама которого, кстати, последние пару недель находится абсолютно везде что в интернете, что на улице )
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также небольшая подборка на смежную тему из нового курса:
- Подключение дисплея на базе ST7735 к микроконтроллеру STM32.
- Дисплей на базе ST7735 и STM32. Вывод изображения.
- Дисплей на базе контроллера SSD1306. Библиотека для STM32.
- STM32 и семисегментный индикатор. Динамическая индикация.
Итак, мы подготовили то, что надо загрузить в память дисплея. Необходимо как-то преобразовать готовую картинку в массив чисел, соответствующих каждому отдельному пикселю. Но для начала конвертируем наш файл в формат bmp, это нам понадобится для дальнейших махинаций. Для того, чтобы получить необходимые данные из bmp файла воспользуемся отличнейшей утилитой от Segger под названием Segger Bitmap Converter. Дружно скачиваем ее, устанавливаем и запускаем.
Давайте разбираться как с помощью этой программы конвертировать изображение в нужный нам вид. А довольно-таки просто. Заходим в меню File->Open и первым делом загрузим нашу картинку. Кстати, ее необходимо еще повернуть на 90 градусов, чтобы она легла на дисплей как надо. Получаем вот что:
В меню Image видим интересный пункт Convert To... Но я, честно говоря, не понял практического смысла этой кнопки, поскольку даже при адском тыкании на разные выходные форматы ничего так и не произошло ) Поэтому идем снова в меню File и жмем на Save As. В появившемся диалоговом окне задаем имя файла, а в поле тип файла выбираем ”C” bitmap file:
Появляется еще одно окно и вот тут то уже мы можем выбрать требуемый формат. Выбираем High Color (565), red and blue swapped и, нажав ОК, получаем готовый .с файл с сохраненным массивом данных для нашего изображения.
Далее я последовал следующий путем. В проект из предыдущей статьи (ссылка была в начале) я добавил еще один файл fsmc.h, в котором объявил массив и просто скопировал в него значения, которые выдала утилита Segger Bitmap Converter. Получилось вот что:
/***************************************************************************************/ const unsigned short picture[] = { 0x0021, 0x0021, 0x0021, 0x0021, 0x0042, 0x0042, 0x0042, 0x0042, 0x0063, 0x0063, 0x0063, 0x0063, 0x0084, 0x0084, 0x0084, 0x0084, 0x0085, 0x00A5, 0x00A5, 0x00C5, 0x00C6, 0x00C6, 0x00E6, 0x00E7, 0x00E7, 0x0107, 0x0108, 0x0108, 0x0128, 0x0128, 0x0129, 0x0129, 0x0149, 0x0149, 0x0149, 0x0149, 0x014A, 0x014A, 0x014A, 0x014A, 0x014A, 0x014A, 0x014A, 0x014A, 0x014B, 0x016B, 0x014B, 0x014B, 0x014B, 0x014B, 0x012B, 0x010A, 0x00E9, 0x00E9, 0x00C9, 0x00A8, 0x00A9, 0x00A8, 0x00A8, 0x00A8, 0x00A8, 0x00A8, 0x00C9, 0x00C9, 0x00EA, 0x00EA, 0x012B, 0x014B, 0x014C, 0x016C, 0x016C, 0x014B, 0x012B, 0x010B, 0x010A, 0x010A, 0x010A, 0x010B, 0x014B, 0x016C, 0x018C, 0x016C, 0x016C, 0x018C, 0x018C, 0x018C, 0x016B, 0x016B, 0x016B, 0x016C, 0x018C, 0x016C, 0x014B, 0x010B, 0x010B, 0x010B, 0x012B, 0x012B, 0x012B, 0x012B, 0x012B, 0x010A, 0x010A, 0x012B, 0x00EA, 0x010A, 0x00C8, 0x00A8, 0x0108, 0x00E8, 0x0149, 0x224D, 0x094A, 0x0108, 0x096A, 0x098A, 0x0129, 0x0129, 0x0109, 0x0129, 0x0108, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x0108, 0x0109, 0x0108, 0x0108, 0x00E8, 0x00E7, 0x00E8, 0x00E8, 0x0108, 0x00E8, 0x00C7, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x00E8, 0x0108, 0x0108, 0x0108, 0x0108, 0x0129, 0x0129, 0x0149, 0x0149, 0x0149, 0x0149, 0x016A, 0x016A, 0x016A, 0x016A, 0x016A, 0x016A, 0x018A, 0x018A, 0x018A, 0x018B, 0x018B, 0x01AB, 0x01AB, 0x01AB, 0x01AB, 0x01AB, 0x01CB, 0x01CB, 0x01CB, 0x01CB, 0x01CB, 0x01EC, 0x01CC, 0x01CC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01EC, 0x01ED, 0x01ED, 0x01ED, 0x01ED, 0x01ED, 0x020D, 0x020D, 0x020D, 0x020D, 0x020D, 0x020D, 0x020D, 0x020D, 0x022D, 0x022D, 0x022D, 0x022D, 0x022D, 0x022D // ...и дальше еще море различных значений... /***************************************************************************************/
Теперь еще пара небольших правок в функции main():
/***************************************************************************************/ int main() { int i; initAll(); initLCD(); // Начальный и конечный адреса по горизонтали writeLCDCommand(0x0050, 0); writeLCDCommand(0x0051, 239); // Начальный и конечный адреса по вертикали writeLCDCommand(0x0052, 0); writeLCDCommand(0x0053, 319); writeLCDCommand(32, 0); writeLCDCommand(33, 0); *(uint16_t *) (LCD_REG) = 34; for (i = 0; i < 76800; i++) { writeLCDData(picture[i]); } delay(0x0FFFFF); while(1) { } } /***************************************************************************************/
И вот, в принципе, все готово. Заливаем программу в контроллер и получаем результат:
В дальнейшем думаю еще что-нибудь замутим с STM32 и дисплеем, что-то мне понравилось это дело )