Продолжаем серию публикаций, посвященных использованию среды ARM mbed для создания прототипа измерительного устройства.
Напомню, что речь идет о разработке устройства с сенсорным экраном, которое служит для высокоскоростного измерения температуры и относительной влажности. Самое интересное в этой истории — подход к созданию встроенного ПО. Для написания программы используется онлайн IDE mbed, позволяющая создавать железонезависимый код, который одинаково работает на отладочных платах от SiLabs, Atmel, Wiznet, STM32, NXP и других производителей.
Сегодня начинаем работать с выводом картинки на TFT-дисплей.
Содержание цикла публикаций:
- Обзор использованных программных и аппаратных решений.
- Начало работы с графическим контроллером FT800. Использование готовых mbed-библиотек для периферийных устройств.
- Подключение датчика HYT-271. Создание и публикация в mbed собственной библиотеки для периферийных устройств.
- Разработка приложения: Структура программы, работа с сенсорным экраном.
- Разработка приложения: Вывод изображений на дисплей, проблемы русификации.
- Печать деталей корпуса. Анализ ошибок проектирования и другие выводы.
Вторая часть под катом.
В прошлой статье был дан краткий обзор использованных аппаратных модулей, в том числе сенсорного TFT-дисплея — модуля от компании Riverdi, который состоит из дисплея и встроенного графического контроллера FT800 от FTDI. Сегодня мы рассмотрим общие вопросы работы с таким модулем и «подружим» его с отладочной платой.
Поскольку для написания ПО используется исключительно онлайн IDE mbed, получившаяся программа должна без проблем запуститься на отладочных платах SLSTK3400A от SiLabs, ATSAMD21-XPRO от Atmel и WIZwiki-W7500P от Wiznet.
Итак, все процедуры, связанные с выводом графики, сенсорным вводом и работой аудиоканала, аппаратно реализованы на графическом контроллере серии FT800. Задачей разработчика является управление микросхемой FTDI с главного микроконтроллера — грубо говоря, чтение и запись определенных регистров контроллера FT800 по интерфейсу SPI или I2C*.
* далее будем считать что хост-контроллер связан с FT800 по интерфейсу SPI. Чаще всего так и есть.
Для управления графическим контроллером используются команды трех типов:
- Host command для управления режимом работы FT800,
- Host Memory Read для получения информации с контроллера FTDI (например, для чтения регистра сенсорного ввода)
- Host Memory Write для передачи команд на выполнение графических операций, на воспроизведение звука и т.д.
Все функции для взаимодействия с TFT-дисплеем состоят из приема и передачи таких команд. Компания FTDI предоставляет библиотеку, в которой реализованы все операции, поддерживаемые графическим контроллером. Это несколько десятков функций различной сложности, которые, тем не менее, всегда состоят их базовых функций — приема и передачи по SPI инструкций Host command, Host Memory Read и Host Memory Write.
В общем случае для начала работы с дисплеем требуется адаптировать под используемый хост-контроллер те функции библиотеки FTDI, которые обращаются к периферийным устройствам управляющего контроллера. Это настройка интерфейса SPI, а также функции чтения и записи по SPI данных заданного формата. После того, как железозависимые функции изменены в соответствии с особенностями хост-контроллера, можно начинать использовать все возможности библиотек и примеров от FTDI.
О том, где скачать библиотеку и примеры для модулей FT800, о том как адаптировать библиотеку под целевой хост-микроконтроллер и как использовать доступные функции для практических задач, можно узнать из материалов от производителя и из статей моего коллеги Сергея Долгушина:
- Графический контроллер FT800 для управления TFT-дисплеями – обзорная статья, которая знакомит с основными возможностями графических контроллеров FTDI.
- Графический контроллер FT800. Программные средства разработки и отладки. – в статье рассмотрены полезные утилиты и библиотеки, которые существенно упрощают этапы освоения, разработки и тестирования графических приложений, а также помогают познакомиться с функциональными возможностями FT800/801 с помощью персонального компьютера без использования дополнительных аппаратных средств.
- Начинаем работать с графическим контроллером FT800 FTDI – пример использования графического контроллера FT800 с микроконтроллерами Cypress. Описаны основные этапы по адаптации библиотеки производителя для выбранного МК.
- Графический контроллер EVE FT800 FTDI. Работа с пользовательскими шрифтами, кнопками и сенсорным экраном. – продолжение предыдущей статьи, в которой рассмотрены основные принципы работы с элементами пользовательского интерфейса и сенсорным экраном. В частности, показано, как FT80x обрабатывает информацию от сенсорного экрана и автоматически привязывает ее к заданному элементу интерфейса.
- Графический контроллер EVE FT800 FTDI и микроконтроллер SAMD21 Atmel. Работаем с графическими изображениями. – Пример адаптации библиотеки производителя для использования с МК Atmel серии SAM D21 и работа с графическими объектами.
- Графический контроллер EVE FT800 FTDI и микроконтроллер SAMD21 Atmel. – продолжение предыдущей статьи, в которой описана методика работы с JPEG-изображениями.
- Графический контроллер FT800. Вывод на экран изображения стрелочного индикатора – в данном примере описана методика, которая позволяет минимизировать обмен данными между МК и графическим контроллером за счет использования встроенного ОЗУ FT80x.
В случае разработки программы в mbed задача упрощается ещё сильнее — поскольку написанный в mbed код сам по себе является железонезависимыми, то даже базовые функции библиотеки FTDI становятся универсальными. Таким образом, для управлением дисплеем с отладочных плат от разных производителей можно использовать одну и ту же mbed-библиотеку без внесения каких-либо изменений.
Схема подключения
Для подключения TFT-модуля требуется восемь сигналов:
- четыре линии SPI — mosi, miso, sck и ss
- Сигнал intr (interrupt от контроллера FTD хост-контроллеру),
- Сигнал pd — power down,
- Питание (3.3 В) и земля.
Сигналы intr и pd могут быть реализованы на любых свободных цифровых линиях хост-контроллера.
Для большинства TFT-модулей Riverdi подключение модуля к управляющему контроллеру производится через плоский шлейф. Для подключения шлейфа к отладочным платам предлагается плата-переходник Break Out Board 20. При её использовании нужно обратить внимание на то, что кроме линии питания VDD, на плате отдельно выведено питание подсветки дисплея — сигнал BLVDD. Для работы с дисплеем питание должно подаваться и на VDD, и на BLVDD, поэтому есть смысл сразу объединить линии и подавать питание только на VDD.
С землями GND и BLGND такой фокус не требуется.
Процедура инициализации TFT-модуля
Процедура инициализации состоит из трех этапов: настройка интерфейса SPI, инициализация графического контроллера FT800 и инициализация TFT-дисплея.
Интерфейс SPI хост-процессора всегда является мастером и работает в режиме “mode 0” с передачей старшего бита первым (MSB first). Максимальная рабочая частота интерфейса — 30 МГц, однако до окончания процедуры инициализации частота не должна быть задана выше 11 МГц.
Инициализация графического контроллера состоит в последовательном выполнении следующих операций.
Сначала сигнал PD переводится на 20 мс в низкий уровень, а затем ещё на 20 мс в высокий уровень. Таким образом графический контроллер переходит в режим готовности (Standby). После этого на контроллер FTDI подается несколько команд группы Host command: командой ACTIVE (0x00) контроллер переводится в активный режим, командой CORERST (0x68) сбрасываются значения всех регистров и логических цепей, далее командой CLKEXT (0x44) выбирается тактирование от внешнего источника, а после этого выбирается рабочая частота контроллера — 48 или 36 МГц командой CLK48M (0x62) или CLK36M (0x61) соответственно.
Конечно, возможны и другие сценарии настройки контроллера FT800, но чаще всего процедура выглядит именно так.
Если инициализация графического контроллера прошла успешно, то в регистре REG_ID графического контроллера устанавливается значение 0x7C. После проверки этого контрольного значения можно увеличить скорость SPI.
Последним подготовительным этапом является настройка параметров TFT-дисплея. Суть процедуры — запись в определенные регистры графического контроллера параметров конкретного TFT-дисплея. Мы один раз объясняем графическому контроллеру к какому именно дисплею он подключен, а потом используем универсальные библиотечные функции.
После настроек на дисплей выводится пустой экран. Далее, при необходимости, проводятся настройка сенсорного ввода и аудиоканала. Все эти процедуры многократно описаны производителем, поэтому, наверное, не нуждаются в пояснениях.
Вывод на дисплей графических примитивов и виджетов
После инициализации работа с дисплеем сводится к формированию очередного дисплей-листа и загрузке его на графический контроллер. Дисплей-лист — это список команд, в результате исполнения которых контроллер FTDI выводит на дисплей некое изображение.
Дисплей-лист начинается с записи в графический контроллер команды CMD_DLSTART и заканчивается записью команды DISPLAY(). Отображение дисплей-листа происходит по записи стандартного значения в регистр REG_DLSWAP.
В теле дисплей-листа может находиться до 2048 инструкций. Все они представляют собой простые команды вроде задания цвета объектов и отрисовки графических примитивов — линий, прямоугольников, точек и т.д.
Графический контроллер FTDI состоит из нескольких узлов, среди которых основной процессор, дополнительный графический сопроцессор, аудиосопроцессор и т.д. За выполнение простых команд дисплей-листа отвечает основной процессор FT800, однако микросхемы FTDI позволяют работать и с более сложными объектами — виджетами. Виджеты — это кнопки, слайдеры, шкалы, градиенты, текстовые строки, числа и так далее. Несмотря на то что отрисовка виджетов осуществляется сопроцессором, при формировании дисплей-листа можно вперемешку вызывать простые базовые функции и функции отрисовки виджетов.
Использование библиотеки FT800 в собственном mbed-проекте
В прошлой статье была подготовлена заготовка проекта — короткая программа, выводящая на виртуальный COM-порт счетчик секунд. Сегодня подключим к проекту библиотеку FT800 и будем выводить счетчик секунд уже на TFT-дисплей.
Среди mbed-разработчиков уже нашелся человек, имевший дело с графическим контроллером FT800. Этот самый человек, Peter Drescher, благополучно адаптировал для mbed библиотеку от FTDI, снабдил её примером использования и фотографиями. Спасибо, Peter!
Чтобы использовать библиотеку в своем проекте, кликаем на на Import library на посвященной FT800 странице, попадаем в свой компилятор и выбираем проект, к которому библиотека будет подключена. Разумеется, для всех этих телодвижений нужно предварительно зарегистрироваться на developer.mbed.org.
Для использования библиотеки FT800 нужно подключить к своему main.cpp файл FT_Platform.h и объявить новый объект TFT класса FT800, также как мы объявляли объект pc класса Serial в программе из предыдущей статьи. Аргументами при объявлении объекта служат выводы платы, на которых доступны линии интерфейса SPI и сигналы PD и INT. Поскольку я буду запускать программу на трех разных платах, сразу расписываю распиновку для всех трех случаев:
#include "mbed.h"
#include "FT_Platform.h"
// SLSTK3400A
FT800 TFT (PE10, PE11, PE12, PE13, PB11, PD4); // mosi, miso, sck, ss, int, pd
// WIZwiki-W7500P
//FT800 TFT (D11, D12, D13, D10, D9, D8); // mosi, miso, sck, ss, int, pd
// ATSAMD21-XPRO
//FT800 TFT (PA18, PA16, PA19, PA17, PA20, PA21); // mosi, miso, sck, ss, int, pd
Сам конструктор класса FT800 лежит в файле FT_Gpu_Hal.cpp
FT800::FT800(PinName mosi, PinName miso, PinName sck, PinName ss, PinName intr, PinName pd):
_spi(mosi, miso, sck),
_ss(ss),
_pd(pd),
_f800_isr(InterruptIn(intr))
{
_spi.format(8,0); // 8 bit spi mode 0
_spi.frequency(2000000); // start with 10 Mhz SPI clock
_ss = 1; // cs high
_pd = 1; // PD high
Bootup();
}
В конструктор класса FT800 уже включена вся процедура инициализации TFT-модуля — настройка интерфейса SPI и вызов функции Bootup(), которая описывает подачу 20-милисекундного импульса на линию PD, отправку нужной последовательности Host-команд, проверку REG_ID графического контроллера, дальнейшее задание частоты SPI в 20 МГц, а также настройка параметров TFT-дисплея.
Смотреть код можно здесь (листать в конец страницы).
Важно отметить, что дефайны для параметров TFT-дисплея задаются в файле FT_LCD_Type.h, где по умолчанию прописаны параметры дисплея стандарта WQVGA с разрешением 480 на 272.
Вы поймете что дисплей правильно подключен и корректно инициализирован, если после отработки конструктора загорелся белый экран, в любом другом случае нужно искать ошибку. Если же всё сделано правильно, можно начинать формировать первый дисплей-лист.
Приведу пример простой программы для вывода на экран счетчика секунд, круглых часов и ещё нескольких объектов.
Единственный дисплей-лист будет состоять из следующих операций:
1. Начало дисплей-листа, установка белого цвета как цвета по умолчанию:
TFT.DLstart();
TFT.DL(CLEAR_COLOR_RGB(255, 255, 255));
TFT.DL(CLEAR(1, 1, 1));
2. Установка черного цвета, вывод двух текстовых строк:
TFT.DL(COLOR_RGB(0, 0, 0));
TFT.Text(11, 15, 30, 0, "Demo-project for habrahabr.ru");
TFT.Text(13, 15 + 40, 28, 0, "Using FT800 library");
3. Установка темно-зеленого цвета, вывод графического примитива «Прямоугольник»:
TFT.DL(COLOR_RGB(9, 35, 5));
TFT.DL(BEGIN(RECTS));
TFT.DL(VERTEX2II(11, 105, 0, 0));
TFT.DL(VERTEX2II(11 + 275, 105 + 100, 0, 0));
4. Установка белого цвета, вывод текста и числа секунд:
TFT.DL(COLOR_RGB(255, 255, 255));
TFT.Text(11 + 10, 105 + 10, 29, 0, "Number of seconds:");
TFT.Number(11 + 10, 105 + 10 + 30, 31, 0, seconds);
5. Вывод одного из поддерживаемых на FT800 виджетов — часов:
TFT.Clock(390, 105 + 70, 70, 0, 4, 20, (seconds % 60), 0);
6. Установка черного цвета, вывод текстовой строки:
TFT.DL(COLOR_RGB(0, 0, 0));
TFT.Text(11, 240, 28, 0, "e-mail: xk@efo.ru");
7. Вывод графического примитива «Прямая линия»:
TFT.DL(BEGIN(LINES));
TFT.DL(LINE_WIDTH(8));
TFT.DL(VERTEX2II(11, 15 + 40 + 30, 0, 0));
TFT.DL(VERTEX2II(460, 15 + 40 + 30, 0, 0));
8. Конец дисплей-листа, загрузка картинки на дисплей:
TFT.DL(DISPLAY());
TFT.Swap();
Обращаю внимание, что команды TFT.DL() — это описанные выше простые команды дисплей-листа, а команды TFT.Text(), TFT.Number() и TFT.Clock() — это инструкции сопроцессора.
Важно!
Для графических контроллеров серии FT800 в mbed доступно две библиотеки одного и того же автора — FT800 и FT800_2. Отличаются они друг от друга только названиями функций: в первой библиотеке используются те же названия, что в материалах от FTDI, а во второй все названия сокращены:
TFT.Ft_Gpu_CoCmd_Dlstart(); TFT.Ft_App_WrCoCmd_Buffer(CLEAR_COLOR_RGB(255, 255, 255)); TFT.Ft_App_WrCoCmd_Buffer(CLEAR(1, 1, 1)); TFT.Ft_App_WrCoCmd_Buffer(BEGIN(LINES)); TFT.Ft_App_WrCoCmd_Buffer(DISPLAY()); |
TFT.DLstart(); TFT.DL(CLEAR_COLOR_RGB(255, 255, 255)); TFT.DL(CLEAR(1, 1, 1)); TFT.DL(BEGIN(LINES)); TFT.DL(DISPLAY()); |
Я использую второй вариант, однако у использования длинных названий функций есть неоспоримое преимущество: освоившись в таких именах вам будет гораздо легче использовать примеры от производителя и утилиты для автоматической генерации кода от FTDI.
Возвращаемся к примеру работы с дисплеем, программе для вывода счетчика секунд на TFT. За основу берем проект-заготовку из прошлой статьи, в котором с помощью базовой библиотеки mbed на последовательный интерфейс выводится счетчик секунд.
#include "mbed.h"
Serial pc(USBTX, USBRX);
Ticker timeKeeping;
volatile uint64_t seconds = 0;
void secondsCallback(void) {
pc.printf("Number of seconds: %xrn", seconds);
seconds ++;
}
int main() {
timeKeeping.attach(&secondsCallback, 1.0f);
while(1) {}
}
Вносим соответствующие изменения — подключаем библиотеку FT800, объявляем объект класса FT800 и вы бесконечном цикле вызываем функцию, формирующую описанный выше дисплей-лист.
#include "mbed.h"
#include "FT_Platform.h"
FT800 TFT (PE10, PE11, PE12, PE13, PB11, PD4); // mosi, miso, sck, ss, int, pd [SLSTK3400A]
//FT800 TFT (D11, D12, D13, D10, D9, D8); // mosi, miso, sck, ss, int, pd [WIZwiki-W7500P]
//FT800 TFT (PA18, PA16, PA19, PA17, PA20, PA21); // mosi, miso, sck, ss, int, pd [ATSAMD21-XPRO]
Ticker timeKeeping;
volatile uint64_t seconds = 0;
/***********************************************************************************************************************/
void secondsCallback(void)
{
seconds ++;
}
/***********************************************************************************************************************/
/* Construct the screen and downloasd it to the TFT */
void drawTimeScreen(void)
{
TFT.DLstart();
TFT.DL(CLEAR_COLOR_RGB(255, 255, 255));
TFT.DL(CLEAR(1, 1, 1));
TFT.DL(COLOR_RGB(0, 0, 0));
TFT.Text(11, 15, 30, 0, "Demo-project for habrahabr.ru");
TFT.Text(13, 15 + 40, 28, 0, "Using FT800 library");
TFT.DL(COLOR_RGB(9, 35, 5));
TFT.DL(BEGIN(RECTS));
TFT.DL(VERTEX2II(11, 105, 0, 0));
TFT.DL(VERTEX2II(11 + 275, 105 + 100, 0, 0));
TFT.DL(COLOR_RGB(255, 255, 255));
TFT.Text(11 + 10, 105 + 10, 29, 0, "Number of seconds:");
TFT.Number(11 + 10, 105 + 10 + 30, 31, 0, seconds);
TFT.Clock(390, 105 + 70, 70, 0, 4, 20, (seconds % 60), 0);
TFT.DL(COLOR_RGB(0, 0, 0));
TFT.Text(11, 240, 28, 0, "e-mail: xk@efo.ru");
TFT.DL(BEGIN(LINES));
TFT.DL(LINE_WIDTH(8));
TFT.DL(VERTEX2II(11, 15 + 40 + 30, 0, 0));
TFT.DL(VERTEX2II(460, 15 + 40 + 30, 0, 0));
TFT.DL(DISPLAY());
TFT.Swap();
}
/***********************************************************************************************************************/
int main()
{
timeKeeping.attach(&secondsCallback, 1.0f);
while(1) {
drawTimeScreen();
}
}
Проект доступен по ссылке.
Чтобы получить файл прошивки для трех разных отладочных плат нужно, как и в прошлый раз, изменить целевую платформу в правом верхнем углу окна компилятора, а также изменить названия линий ввода-вывода. Вуаля — программа компилируется и работает на всех трех платах.
В следующей статье будет описан процесс создания и подключения к нашему проекту библиотеки для датчика температуры и относительной влажности HYT-271. Будем потихоньку приближаться к полноценному приложению, работа которого продемонстрирована на видео.
Заключение
В заключении традиционно благодарю читателя за внимание и напоминаю, что вопросы по применению продукции, о которой мы пишем на хабре, можно также задавать на email, указанный в моем профиле.
Автор: ЭФО