Библиотека для работы с TFT-дисплеем на контроллере BD663474.
Библиотека написана для дисплея 240х320 TFT 2.2 от WaveShare на контроллере BD663474. Язык - Си, среда разработки - Keil uVision 5, генератор кода - STM32 CubeMX. В качестве железа была использована отладочная плата STM32 NUCLEO-F446RE с микроконтроллером STM32F446RET6. Обмен данными организован по SPI. Есть возможность выбора работы на аппаратном или программном SPI. Имеется поддержка UTF-8 (только кириллица).
Библиотека содержит основные функции для рисования графики и вывода текста на дисплей. Подробное описание находится в BD663474.h
TFT_init(uint8_t orientation, SPI_HandleTypeDef *displaySPI)
- инициализация дисплея. Во втором аргументе укажите ссылку на интерфейс SPI. В режиме программного SPI второй аргумент отсутствует.TFT_setOrientation(uint8_t orientation)
- сменить ориентацию дисплея. Список ориентаций находится вBD663474.h
TFT_reset(void)
- аппаратная перезагрузка дисплеяTFT_Off(void)
- выключить дисплейTFT_On(void)
- включить дисплейTFT_clear(void)
- очистить дисплейTFT_setColor(uint16_t color)
- установить текущий цвет рисования. Подходит для текста, например. Список цветов находится вBD663474.h
TFT_getColor(void)
- получить текущий цвет рисования. Можно использовать макросTFT_COLOR_CURRENT
TFT_setCursor(uint16_t X, uint16_t Y)
- установить положение курсора на экране. Подходит для текстаTFT_getCursorX(void), TFT_getCursorY(void)
- получить текущие значения положения курсора по X и YTFT_test(void)
- функция тестирования дисплея. В коде можно посмотреть как пользоваться теми или иными функциямиTFT_RGB(uint8_t R, uint8_t G, uint8_t B)
- преобразовать RGB в 16-ти битный формат 565
TFT_fillDisplay(uint16_t color)
- залить дисплей указанным цветомTFT_drawImage(uint16_t width, uint16_t height, const uint16_t *bitmap)
- нарисовать картинкуTFT_drawPixel(uint16_t x, uint16_t y, uint16_t color)
- закрасить пиксель по координатам X,Y указанным цветомTFT_drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t size, uint16_t color)
- нарисовать линию начиная с x0,y0, заканчивая x1,y1 указанным цветомTFT_drawLineHorizontal(uint16_t x, uint16_t y, uint16_t len, uint8_t size, uint16_t color)
- нарисовать горизонтальную линию начиная с точки (x,y) длиной len указанным цветомTFT_drawLineVertical(uint16_t x, uint16_t y, uint16_t len, uint8_t size, uint16_t color)
- нарисовать вертикальную линию начиная с точки (x,y) длиной len указанным цветомTFT_drawCircle(uint16_t x, uint16_t y, uint16_t radius, uint8_t size, uint16_t color)
- нарисовать окружность с центром в координате (x,y), радиусом radius и указанным цветомTFT_drawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, uint16_t color)
- нарисовать прямоугольник начиная с точки (x,y), с указанной шириной, висотой, шириной линии и цветомTFT_drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t size, uint16_t color)
- нарисовать треугольник по координатам вершин и указанным цветомTFT_drawQuadrant(int16_t x, int16_t y, int16_t radius, uint8_t size, uint8_t c, uint16_t color)
- нарисовать четверть круга с центром (x,y), с указанным радиусом, фазой и цветомTFT_drawRoundRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius, uint16_t size, uint16_t color)
- нарисовать прямоугольник с скруглёнными углами начиная с точки (x,y), с указанной длиной, шириной, радиусом скругления и цветомTFT_fillRectangle(uint16_t x, uint16_t y, uint16_t lenght, uint16_t width, uint16_t color)
- залить прямоугольник начиная с точки (x,y), с указанной длиной, шириной и цветомTFT_fillCircle(uint16_t x, uint16_t y, uint16_t radius, uint16_t color)
- залить окружность с центром в координате (x,y), радиусом radius и указанным цветомTFT_fillQuadrant(int16_t x, int16_t y, int16_t radius, uint8_t c, int16_t delta, uint16_t color)
- закрасить четверть круга с центром (x,y), с указанным радиусом, фазой и цветомTFT_fillRoundRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius, uint16_t color)
- закрасить прямоугольник с скруглёнными углами начиная с точки (x,y), с указанной длиной, шириной, радиусом скругления и цветом
TFT_setFont(TFT_font *font)
- установить текущий шрифт текстаTFT_setFontSize(uint8_t size)
- установить размер шрифта, стандартный размер умножается на указанное числоTFT_printChar(char c)
- напечатать один символTFT_printCharUTF8(uint16_t c)
- напечатать двухбайтный символTFT_print(uint8_t x, uint8_t y, char str[])
- печать строки начиная с указанной координатыTFT_setTextBackColor(uint16_t color)
- установить цвет фона текста. TFT_COLOR_none - прозрачный
TFT_sendData(uint16_t data)
- отправить 2 байта данных на дисплейTFT_sendCmd(uint16_t cmd, uint16_t data)
- отправить команду и её данные на дисплейTFT_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
- ограничить рабочую область от (x0,y0) до (x1,y1)
Для подключения используются 5 проводов:
- RESET - ножка сброса дисплея
- CS - chip select, указание контроллеру дисплея что работаем именно с ним
- RS - переключение между отправкой данных/команды
- MOSI - линия данных SPI
- SCK - линия тактирования SPI
После подключения к микроконроллеру, по необходимости, подправьте в BD663474.h
макросы работы с пинами. Если вы используете CubeMX, настройте порты на выход и укажите название пинов RESET, CS и RS как на рисунке:
Использовать библиотеку достаточно просто. Например:
#include "BD663474.h"
...
int main(void) {
...
const unsigned short otter[] ={...};
TFT_init(TFT_ORIENT_LANDSCAPE, &hspi1);
TFT_setColor(TFT_COLOR_White);
TFT_clear();
TFT_setFontSize(3);
TFT_print(10,0, "Привет, выдра! :)");
TFT_setCursor(90,100);
TFT_drawImage(140,105, otter);
...
}
Испытать работу дисплея можно вызвав функцию TFT_test(void)
. В ней же можно посмотреть примеры использования остальных функций.
Пример показан на рисунке. Обязательно укажите длину посылки 16 бит. Дисплей прекрасно работает на частоте SPI 45 МГц и ниже, выше 45 МГц испытания не проводились. Использование DMA лишь замедляет работу из-за коротких посылок.
Для использования программного SPI раскомментируйте макрос TFT_SOFTSPI
в BD663474.h
и подкорректируйте соответствующие макросы для MOSI и SCK. На STM32 не забудьте установить максимальную частоту тактирования портов.
A: Причин может быть несколько:
- Плохой контакт соединительных проводов или неправильное подключение.
- Недостаточное или зашумлённое питание. Попробуйте продублировать провода питания или припаять конденсатор на 1000 мкФ по питанию прямо на гребёнку дисплея.
- Неправильно указаны макросы для работы с портами или неправильно настроен SPI.
A: Проблема в питании. Помогает дублирование проводов питания или конденсатор 1000 мкФ по питанию прямо на гребёнку дисплея.
A: Воспользуйтесь этим конвертором.
A: Раскомментируйте макрос TFT_UTF8_SUPPORT
в BD663474.h
.
Q: Вместо текста отображаются закрашенные прямоугольники или вовсе микроконтроллер зависает, что делать?
A: удалить среду разработки Попробуйте воспользоваться другим компилятором. Лично я в Keil uVision рекомендую использовать 6 версию компилятора с такими настройками:
A: Вы не слышали про sprintf? Тогда мы идём к вам!
#include <stdlib.h>
...
int number = 10;
int main(void) {
...
char buff[5];
sprintf(buff, "%d", number);
TFT_print(0,0,buff);
}
А можно поступить ещё круче - перегрузить fpuc() и пользоваться printf:
#include <stdio.h>
...
int fputc(int c, FILE * stream) {
TFT_printChar(c);
return c;
}
...
int main(void) {
...
float temp = getTemp();
printf("Temp: %.1fC", temp);
}
A: В BD663474.h
поменяйте значения макросов для работы с портами ввода/вывода и переделайте функцию TFT_sendCmd() под ваше железо. Можно переключиться на программный SPI если хотите быстрее портироваться.
А: Скорее всего дело в скорости работы SPI или нестабильном напряжении питания. Попробуйте понизить скорость или отключить другие устройства от шины, оставив только дисплей. Так же попробуйте припаять конденсатор на 1000 мкФ по питанию прямо на гребёнку дисплея.
А: Тачскрин - это совсем другая история.
Предложения или найденные баги можно сообщить в Telegram http://t.me/rainbowkiwifox, ВКонтакте https://vk.com/rainbowkiwifox или на почту [email protected]