STM Урок 179. HAL. Дисплей TFT 240×320. SPI. Часть 1



На данном уроке мы попробуем к контроллеру STM32 подключить дисплей TFT разрешением 240×320.

С подобным дисплеем мы уже работали в далёком уроке 37, только это был модуль, в котором подключение дисплея к контроллеру происходило по 8-битной шине. Тогда мы использовали для этого FSMC контроллера STM32. Это такой удобный контроллер памяти.

А теперь мы попытаемся подключить модуль с подобным дисплеем, который подключается к контроллеру уже по шине SPI. Данный дисплей также выполнен на контроллере ILI9341. Такой дисплей у меня наконец-то появился. Подключим мы его также к плате STM32F4-Discovery, с которой мы когда-то очень долго работали, причём с дисплеем, подключенным по 8-битной шине, мы также работали, подключая его к такой же отладочной плате. Не каждому удалось заиметь такой дисплей, многие по ошибке, а многие и не по ошибке приобрели дисплей, именно подключенный по шине SPI и просили меня сделать такой урок. Конечно же на такие массовые просьбы я просто не мог не откликнуться, мне прислали именно такой дисплей и мы теперь с ним поработаем, начнём с библиотеки HAL, причём сначала без DMA, потом применим DMA для того, чтобы сравнить, что нам даст эта периферия.

Дисплей выглядит следующим образом

 

 

 

У меня дисплей размером диагонали 2,8 дюймов, могут быть другие размеры, главное, чтобы разрешение было 320×240 и контроллер чтобы был такой же.

Верхние 5 ножек относятся к работе с сенсорной панелью (TouchScreen), поэтому мы их использовать не будем, следующая 6 ножка — MISO тоже не будет нами использована, так как нам нет смысла ничего читать из дисплея, мы знаем, что у нас именно ILI9341, да и не совсем корректно контроллер работает с MISO.

Подключим к нашей отладочной плате только нижние следующим образом

 

 

Вот соответствие ножек на плате и на дисплее

 

STM32F4-Discovery

LCD
5V VCC
GND GND
PA4 CS
PA2 RESET
PA3 DC
PA7 SDI (MOSI)
PA5 SCK
3V

LED

 

Питание мы подаём 5 вольт, так как на плате модуля есть стабилизатор, а подсветку питаем 3-мя вольтами. С шиной SPI мы работаем постоянно, причём на контроллере STM32F1 мы её прошли вдоль и поперёк, применяя различные библиотеки. Думаю, F4 также не станет исключением и мы с ним также будем работать не только с применением библиотеки HAL, но так как с данной библиотекой мы уже работали с шиной SPI на контроллере STM32F4, то, думаю, нам следует пока её и использовать, чтобы не наделать ошибок.

Запустим проектогенератор Cube MX и создадим новый проект, выбрав соответствующий контроллер

 

 

Включим кварцевый резонатор

 

 

Выберем отладчик

 

 

Настроим тактирование в Closk Configuration

 

 

Включим SPI1 и настроим пока небольшую скорость, чтобы не думать, что ошибки из-за слишком высокой скорости, потом прибавим

 

 

У нас включились 3 основные ножки нашей шины. Включим на выход остальные ножки, которые присутствуют в нашей таблице

 

 

Добавим нашим ножкам скорости

 

 

Включим RNG для лучшего формирования случайных чисел

 

 

Немного перестроим частоты в Clock Configuration, чтобы получить вот тут 48, только так, чтобы основная частота осталась максимальной

 

 

Присвоим имя проекту, выберем среду разработки и удвоим размер стека и кучи

 

 

Сгенерируем проект и откроем его в Keil.

 

 

Настроим программатор на автоперезагрузку, отключим оптимизацию и создадим два файла — spi_ili9341.c и spi_ili9341.h для работы с нашим дисплеем следующего содержания

 

 

 

Подключим данную библиотеку в файле main.c

 

 

Перейдём в файл spi_ili9341.c и добавим там функцию инициализации нашего дисплея, объявив в ней пока небольшой локальный массив

 

 

Добавим на данную функцию прототип в заголовочном файле и вызовем её в функции main() файла main.c

 

 

В файле spi_ili9341.h и добавим несколько макросов для управления нашими управляющими ножками

 

 

В файле spi_ili9341.c опустим ножку выбора в функции инициализации

 

 

Выше функции инициализации добавим функцию перезагрузки дисплея

 

 

Вызовем её в функции инициализации

 

 

Подключим переменную структуры шины SPI и RNG

 

 

Выше функции TFT9341_reset добавим функцию отправки команды в дисплей по шине SPI

 

 

Ниже добавим подобную функцию отправки данных в дисплей

 

 

Теперь ниже добавим функцию отправки данных сразу пакетом в определённом количестве

 

 

 

В функции инициализации дисплея произведём также программную перезагрузку и подождём 1 секунду

 

 

Передадим ряд команд с определёнными параметрами в контроллер дисплея для первоначальной настройки дисплея

 

 

Чтобы было более или менее понятно, какие настройки мы проделали, я добавил перед каждой командой комментарии. Да и практически в настройках ничего не изменилось со времён урока 37.

Подождём 120 милисекунд

 

 

Добавим несколько нужных макросов в файл spi_ili9341.h

 

 

Вернёмся в функцию TFT9341_ini файла spi_ili9341.c и включим дисплей, настроив нужную ориентацию экрана

 

 

Добавим две глобальные переменные для хранения размеров экрана

 

 

В функции TFT9341_ini проинициализируем их данными из аргументов функции

 

 

Выше функции инициализации добавим функцию установки адреса, с которого затем будут записываться данные в память дисплея, а также функцию заливки прямоугольника. Данные функции со времён урока 37 у нас также особых изменений не претерпели

 

 

Ниже добавим функцию заливки всего экрана определённым цветом

 

 

Добавим на 2 последние функции прототипы в заголовочный файл

 

 

В функции main() файла main.c зальнём экран каким-нибудь цветом, например, зелёным

 

 

Соберём код, прошьём контроллер и посмотрим результат

 

 

Всё работает, значит мы правильно настроили наш дисплей.

Теперь мы можем немного прибавить скорость шины SPI в Cube MX и перегенерировать проект

 

 

Теперь отправка в дисплей данных будет идти гораздо быстрее.

Давайте теперь попробуем написать какие-нибудь тесты в бесконечном цикле. В принципе, они у нас уже написаны в уроке 37, нам останется только их добавить. Но пойдём по порядку.

Исправим заливку зелёным цветом в чёрный цвет

 

TFT9341_FillScreen(TFT9341_BLACK);

 

Добавим небольшую задержку

 

 

Вернёмся в файл spi_ili9341.c и над функцией инициализации добавим функцию формирования случайного числа с использованием генератора RNG

 

 

Мы накладываем маску на младшие 16 бит числа, так как мы используем 16-разрядные цвета.

Добавим на данную функцию прототип в заголовочном файле, вернёмся в main.c и добавим пару локальных переменных

 

 

В бесконечном цикле функции main() попробуем позакрашивать экран дисплея различными случайными цветами

 

 

Соберём код, прошьём контроллер и посмотрим результат

 

 

Всё отлично заливается. Скорость, конечно, не такая, как при параллельном подключении, но всё же не так уж и медленнее. Использование DMA, я думаю, нам ещё прибавит скорости.

Подключим наши глобальные переменные размера экрана

 

 

Закомментируем предыдущий тест и добавим следующий по заливке экрана прямоугольниками случайного цвета в 4 области экрана. Мы будем при добавлении очередных тестов комментировать предыдущий, чтобы не ждать новых

 

 

Проверим, как работает тест

 

 

Следующий тест будет заливать прямоугольники случайного цвета, случайного размера и в случайные места

 

 

Посмотрим работу теста

 

 

В следующей части урока мы напишем ещё несколько функций по работе с дисплеем, а также и проведём несколько тестов данных функций на практической схеме.

 

 

Предыдущий урок Программирование МК STM32 Следующая часть

 

 

Отладочную плату и дисплей можно приобрести здесь:

STM32F4-DISCOVERY

2,8 дюймов 240×320 SPI TFT LCD

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM Name

2 комментария на “STM Урок 179. HAL. Дисплей TFT 240×320. SPI. Часть 1
  1. Алексей:

    день добрый, посмотрел урок 180 с ДМА, где вы показали задержку в заливке экрана. У вас долгая заливка экрана из-за отправки пакета по 2 байта, попробуйте такую реализацию отправки пакета. думается мне что это будет равнозначно отправки по ДМА, разумеется не считая что во время отправки по ДМА можно заниматься чем то полезным.

    void TFT9341_FillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
    {
    if((x1 >= TFT9341_WIDTH) || (y1 >= TFT9341_HEIGHT) || (x2 >= TFT9341_WIDTH) || (y2 >= TFT9341_HEIGHT)) return;
    if(x1>x2) swap(x1,x2);
    if(y1>y2) swap(y1,y2);
    TFT9341_SetAddrWindow(x1, y1, x2, y2);
    uint8_t data[] = { color >> 8, color & 0xFF };
    uint32_t data_cnt = (x2-x1+1)*(y2-y1+1);
    uint16_t tx_cnt;
    DC_DATA();
    while(data_cnt)
    {
    if(data_cnt > 0xFFFF)
    {
    tx_cnt = 0xFFFF;
    }
    else
    {
    tx_cnt = data_cnt;
    }
    HAL_SPI_Transmit(&hspi1, data, tx_cnt, HAL_MAX_DELAY);
    data_cnt -= tx_cnt;
    }
    }

  2. Сергей:

    Здравствуйте.
    Подскажите пожалуйста , Keil5 выдает в этих строках ошибку

    if(x1>x2) swap(x1,x2); error: expected ';' alfter expression
    if(y1>y2) swap(y1,y2); error: expected ';' alfter expression

    в чем может быть дело?
    С уважением
    Сергей

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*