И невозможное станет возможным RGB-интерфейс, реализованный на микроконтроллере за $1

№ 2’2012
Управление LCD TFT — это задача, которая потребует большой производительной мощности микроконтроллера. Однако разработчик приложения, успешно освоивший не очень мощный микроконтроллер, вполне может управлять LCD TFT через плату посредника, которой комплектуются LCD TFT непосредственно на заводе-изготовителе ЖК-индикаторов.

Методы управления LCD TFT индикатором

Управление LCD TFT — это задача, которая потребует большой производительной мощности микроконтроллера. Однако разработчик приложения, успешно освоивший не очень мощный микроконтроллер, вполне может управлять LCD TFT через плату посредника, которой комплектуются LCD TFT непосредственно на заводе-изготовителе ЖК-индикаторов. Плата-посредник — это изделие, собранное на базе мощного контроллера (как правило, с ядром ARM9 и мощнее) с оперативной памятью, которой достаточно для хранения нескольких кадров изображения. Такое изделие избавляет разработчика от решения множества вопросов вывода изображения на LCD TFT, таких как вертикальная синхронизация формируемой развертки, горизонтальная синхронизация, сигнал синхронизации точки и одновременная выдача данных в RGB-интерфейс (рис. 1). Специалист работает через определенный интерфейс с контекстом памяти, отображаемой на экране. Меняя контекст оперативной памяти платы-переходника, можно сменить выводимое изображение. Требования к внешнему контроллеру — минимальны. Процесс вывода изображения на экран не привязан к процессу формирования изображения в памяти. Низкая производительность управляющего контроллера практически не сказывается на качестве изображения (возможно снижение скорости прорисовки выводимых на экран объектов, но не частоты развертки).

RGB-интерфейс на базе контроллера STM32F100C4T6

Рис. 1. RGB-интерфейс на базе контроллера STM32F100C4T6

Упомянутое решение является классическим, самое главное, что дизайнеры приложений и по сей день голосуют за это решение рублем. Сколько оно стоит? Индикатор c RGB-интерфейсом 5,7″ 320×240×16 бит (с платой питания + сенсорная панель) — 1500 руб., плата управления — мост I8080 RGB-интерфейса — 1000 руб., внешний контроллер — 30 руб. Итого — 2530 руб. за решение.

Компания «Промэлектроника» анонсирует свое решение, исключив из описанного выше дизайна мост I8080-RGB. Таким образом, стоимость решения отображения графической информации на экран 5,7″ 320×240×16 снизится до 1530 руб.

Итак, контроллер за 30 рублей должен формировать изображение и построчно выдавать его на экран. Специалисты, которые занимались вопросами отображения информации на графическом экране, могут возразить: «Это нереально». Однако дизайн уже существует и работает на практике.

Вопросы памяти

В числе первых аргументов того, что невозможно сформировать изображение, а потом выдать его на экран, — отсутствие ОЗУ, достаточной для хранения изображения кадра, в контроллере за 30 рублей. Давайте вычислим требуемый размер ОЗУ для хранения картинки размером 320×240×2, где 320×240 — разрешение в пикселях, а 2 — глубина цвета (65 536 цветов). Перемножив эти цифры, получим 153 600 байт. Память SRAM такого объема будет стоить дороже 100 руб. Что уж говорить о микроконтроллере, у которого на кристалле будет размещена память ОЗУ такого объема.

На самом деле для построения изображения, которое будет выдаваться на экран, вполне достаточно двух строк. Первая, уже построенная строка выдается на экран по RGB-интерфейсу, вторая — параллельно этому процессу строится. Далее строки меняются местами. Процессы идут параллельно. Таким образом, даже если выводится статическая картинка на экран, процессор работает так же, как если бы картинка динамически менялась, так как в процессе вывода изображения на экран каждая его строка заново формируется. Данный метод не является классическим, однако вопросы требуемого объема памяти мы уже сняли. Итак, нам надо хранить в памяти всего 2 строки. Значит, требуемый объем при 16-битном цвете — 320×2×2 = 1280 байт.

Производительность микроконтроллера

Есть мнение, что для формирования изображения необходима высокая производительность микроконтроллера. По факту оказывается, что это требование является достаточным, но не необходимым. Даже если элементарно перемножить разрешение экрана на количество обновлений в секунду, допустим, 10 кадров, получим частоту, с которой должна поступать информация о точке: всего 320×240×10 = 768 кГц. Если взять какой-нибудь 8-битный контроллер, например ATmega16, работающий на частоте 16 МГц, то теоретически он сможет выполнить данную задачу. На практике, скорее всего, частота обновления упадет до единиц герц из-за неожиданных нюансов, которые возникают при более глубоком изучении предмета, при этом вряд ли этот контроллер сможет выполнять хоть сколько-то значимую работу. Программу однозначно придется писать на ассемблере.

С другой стороны, контроллер может не иметь высокопроизводительного ядра, но взамен он обязан иметь производительную и гибко настраиваемую периферию. Это, пожалуй, необходимое условие. Этому условию соответствует STM32F100C4T6 — самый «младший» на данный момент в линейке 32-битных контроллеров STMicroelectronics. Цена такого контроллера — 30 руб. у официальных дистрибьюторов STM в России. Именно на этом микроконтроллере компания «Промэлектроника» и построила свое решение задачи.

Чем же, кроме цены, так хорош STM32F100C4T6? Если посмотреть описание, то вроде бы ничего выдающегося там нет:

  • ядро ARM-Cortex M3 с частотой работы не более 24 МГц;
  • память ОЗУ — 4 кбит;
  • флэш-память — 16 кбит;
  • 6 таймеров (не считая SysTick);
  • 7 каналов обмена DMA;
  • несколько интерфейсов (SPI, I2C, USART, CEC);
  • АЦП (10 каналов);
  • ЦАП (2 канала);
  • корпус LQFP48.

По большому счету обычный контроллер по современным меркам. Однако его уникальные свойства скрыты от тех, кто поверхностно смотрит описания. Есть аналогичные по цене микроконтроллеры на базе ядра Cortex M0 других производителей, которые не обладают такими свойствами. Это обстоятельство лишает возможности получить элегантное решение задачи вывода изображения по RGB-интерфейсу.

Замечательные свойства STM32

Красивое решение поставленной задачи стало возможным благодаря двум свойствам микроконтроллеров STM32: это возможность организации таймеров в сложные структуры и наличие контроллера DMA.

Итак, организация таймеров в сложные структуры. Таймер общего назначения имеет вид, как показано на рис. 2. На данный момент любой контроллер STM32 имеет как минимум два таких таймера. Кроме того, в каждом микроконтроллере STM32 есть таймер с расширенными функциями: добавлен интерфейс определения положения вала двигателя, комплементарные выходы сравнения и внешний сигнал торможения двигателя. В нашем случае таймер с расширенными возможностями можно использовать как таймер общего назначения.

Таймер общего назначения в контроллере STM32F1xx

Рис. 2. Таймер общего назначения в контроллере STM32F1xx

Блок-схема таймера общего назначения выглядит стандартно: есть источник тактирования, который может быть внешним, есть делитель частоты счетного сигнала, есть 16-битный счетчик с регистром перезагрузки/сброса и четыре регистра сравнения/захвата. Мы не будем останавливаться на свойствах таймеров, которые характерны для подавляющего большинства таймеров в контроллерах других фирм-производителей: это всевозможное направление счета, выдача/захват ШИМ-сигналов, однократная работа, счет внешних/внутренних импульсов и т. д. Отметим, что все стандартные возможности в таймерах контроллеров STM32 представлены. Возможности, которых нет в большинстве других контроллеров, показаны на рис. 2: это ITR1–ITR4, а также блок «Триггер/контроллер времени». ITR — это внутренний триггер, который может быть не только счетным, но и управляющим. «Управляющим» означает, что это выход, который может запустить таймер, сбросить его, открыть или закрыть окно для счета импульсов. Какая периферия генерирует сигнал ITR? Ответ — другой таймер. Это позволяет, например, жестко синхронизировать несколько таймеров (рис. 3).

Синхронизация нескольких таймеров

Рис. 3. Синхронизация нескольких таймеров

Таймеры 2, 3 и 4 настроены на запуск при срабатывании ITR1. Событие ITR1 возникает при переполнении таймера 1. Таким образом, произойдет одновременный запуск нескольких таймеров. Используя структуру, показанную на рис. 3, можно индивидуально настроить реакцию каждого таймера, допустим, таймер 2 будет сбрасываться, таймер 3 — менять состояние счета/ожидания на противоположное, а таймер 4 — считать количество переполнений таймера 1. Событием, которое сформирует сигнал ITR, может быть переполнение либо срабатывание одного из регистров сравнения.

Можно собрать из нескольких таймеров один, разрядность которого выше 16. Например, 48-битный таймер (рис. 4).

48-битный таймер

Рис. 4. 48-битный таймер

Каждый из таймеров генерирует счетное событие для другого таймера при переполнении. Таким образом, из трех 16-битных таймеров можно создать один — 48-битный. Эту же структуру можно использовать и для других целей: например, таймер 1 может предоставить окно счета импульсов для 32-битного таймера, образованного таймерами 2 и 3. В данном случае изменится настройка таймера 2: именно он принимает решение о том, как использовать сигнал ITR1.

Автору неизвестен контроллер, который мог бы так гибко настраивать систему таймеров. Именно это свойство легло в основу проекта. Кроме того, важной для проекта оказалась генерация прерываний при работе таймера и инициализация обмена по каналу DMA при переполнении таймера.

Второй периферией, которая учитывалась при создании проекта, оказался контроллер прямого доступа к памяти. Именно с его помощью при переполнении одного из таймеров происходило копирование данных цвета рисуемой на экране точки. Копирование происходило из памяти в порт. При построении строки нужно было копировать массивы из одной области памяти в другую. Эту работу также выполнял контроллер DMA. Ядро всего лишь настраивало DMA на копирование новой области памяти при попадании в прерывание «Копирование по такому-то каналу завершено».

Несколько слов о возможностях контроллера прямого доступа к памяти в простейших микроконтроллерах STM32. Это:

  • 7 каналов обмена.
  • 5 уровней приоритета обмена.
  • Возможность копирования память-память, память-периферия, периферия-память.
  • Копирование 8, 16 и 32 бит данных.
  • Управляемый инкремент адреса источника/приемника данных.
  • Три прерывания: «Копирование завершено», «Половина копирования завершена», «Ошибка копирования».
  • Копирование DMA инициируется программно и почти любой периферией контроллера (таймеры, АЦП, ЦАП, интерфейсы и т. д.).

Таким образом, мощная периферия — основа решения нашей задачи.

RGB-интерфейс

До решения точно сформулируем задачу. Точную постановку задачи можно взять непосредственно из описания на индикатор. Итак, для реализации горизонтальной развертки изображения потребуются сигналы (рис. 5).

Сигналы горизонтальной развертки

Рис. 5. Сигналы горизонтальной развертки

Начало запуска прорисовки новой строки формируется переходом уровня сигнала Hsync из «логической 1» в «0». При этом сигнал DCLK, по переднему фронту которого индикатор считывает данные по цвету точки с линий R0–R5, G0–G5 и B0–B5, выдается постоянно. Однако данные по цвету прорисовываемой точки в строке воспринимаются индикатором при условии, что линия DEN находится в состоянии «лог. 1». Момент появления и длительность сигнала DEN, как и Hsync, стандартизован (должно пройти определенное число импульсов DCLK). Для прорисовки строки из 320 точек требуется 408 тактов DCLK.

Начало прорисовки кадра производится переходом уровня сигнала Vsync из «лог. 1» в «лог. 0» (рис. 6).

Вертикальная синхронизация

Рис. 6. Вертикальная синхронизация

Отметим, что на время кадровой синхронизации приостанавливается генерация выдачи сигнала DEN. Длительность сигнала вертикальной синхронизации также нормируется и измеряется в длительностях прорисовки строки. До начала прорисовки изображения согласно документации индикатора должно быть выдано 18–26 Hsync (строк, не содержащих никакой информации изображения). Забегая вперед, отметим, что в реализованном проекте две такие строки.

Итак, задача: формирование сигналов Hsync, Vsync, DEN и DCLK с синхронно выдаваемыми данными по цвету рисуемой точки R0–R5, G0–G5, B0–B5 из буфера рисуемой строки. Параллельно этому процессу должен идти процесс формирования каждой строки в одном из буферов, подлежащей отображению.

Решение задачи

Настроим таймеры, как показано на рис. 7.

Структура таймеров

Рис. 7. Структура таймеров, решающая задачу выдачи данных на RGB-интерфейс

Именно такая структура применена автором при построении RGB-интерфейса. Автор уверен, что эта структура таймеров не оптимальна, однако ее работа проверена на практике, поэтому будем описывать именно ее.

Таймер 15 задает временную базу для работы всей системы, а также постоянно выдает сигнал DCLK в индикатор. Если мы останавливаем таймер 15, то останавливаются все процессы в системе (в части формирования экранной развертки). Это очень удобно: при входе в прерывание, при необходимости, можно одной командой остановить процесс. Таймер 2, по факту тактируемый сигналом DCLK, формирует сигнал вертикальной развертки VCLK и сигнал VDEN (как показано выше, в структуре таймера общего назначения, возможно до четырех выходов сравнения, что равно четырем формируемым ШИМ-сигналам). Сигналы VDEN и HDEN должны объединиться на внешней логической микросхеме «2И» в сигнал DEN. В этом случае можно будет исключить появление сигнала DEN во время вертикальной синхронизации. Таймер 1 формирует сигналы HDEN и HCLK. Кроме того, синхронно с выдачей переднего фронта HDEN запускается таймер 3, который имеет одинаковую частоту с таймером 15. При переполнении таймера 3 формируется запрос контроллеру прямого доступа к памяти на копирование данных цвета выдаваемого пикселя. Таким образом, данные R1–R5, G0–G5, B1–B5 попадают в порт контроллера.

После 320 копирований DMA выдает прерывание «Копирование завершено». В теле этого прерывания происходит останов таймера 3, а также настройка DMA на следующие 320 копирований из следующего буфера.

После переполнения таймера 1, ответственного за формирование горизонтальной развертки, происходит проверка готовности формируемой строки к выдаче в RGB-интерфейс. Если такая готовность есть, то включается таймер 15, отключенный при входе в прерывание, что автоматически запускает процесс выдачи видеоинформации в следующую строку экрана. Если следующая строка еще не готова, то таймер 15 будет запущен сразу по окончании формирования следующей строки.

По окончании прорисовки кадра формируется прерывание по переполнению таймера 2. В нем происходит обновление видеоинформации в целом: изменение положения, размеров, цвета, области памяти, расположения объектов и т. д. В общем, если должна произойти смена вида картинки при смене кадра, то это лучше сделать именно тут.

Параллельно отображению одной строки идет процесс построения следующей. Оба процесса выполняются периферией при минимальном участии ядра. Для примера, допустим, идет отображение белого квадрата на черном фоне (рис. 8).

Формирование изображения строки

Рис. 8. Формирование изображения строки

Сначала мы настраиваем DMA на копирование видеоинформации заднего плана. В нашем случае — заполняем буфер формируемой строки нулями. Когда DMA закончит копирование, возникнет прерывание «Копирование DMA такого-то канала завершено». Далее, если в будущей строке должен отобразиться белый квадрат, будет запущен процесс копирования единиц в буфер строящейся строки. По окончании копирования начнется прорисовка следующего объекта (например, текста красного цвета), либо, если все объекты прорисованы, проверка возможности построения строки в новом буфере и, в случае необходимости, запущен таймер 15.

Итак, силами периферии мы построили два процесса: формирование изображения будущей строки и выдачу изображения в RGB-интерфейс. Ядро принимает участие исключительно в прерываниях.

Алгоритм работы ядра контроллера

Как было сказано ранее, основная работа по прорисовке объекта, а именно копирование объектов в заданную строку, а также трансляция строки по RGB-интерфейсу выполняется силами периферии. Однако этих операций явно недостаточно, чтобы выдавать полноценную картинку.

Для начала уточним, что представляет собой прорисовываемый объект с точки зрения программы контроллера. Это всегда прямоугольник. Параметры этого прямоугольника:

  • Начало прорисовки по оси абсцисс.
  • Начало прорисовки по оси ординат.
  • Ширина прямоугольника.
  • Высота прямоугольника.
  • Адрес памяти начала объекта: это может быть указатель начала растра либо указатель на одну точку, которая будет иметь код цвета.
  • Управление DMA: главным образом, это количество точек, копируемых за раз, и необходимость инкремента адреса источника после копирования. Например, мы будем формировать одноцветный прямо-угольник. В этом случае при формировании строки мы копируем одну и ту же точку много раз. Нам не требуется инкремент адреса источника. Если мы отображаем растр — картинку из памяти, нам потребуется указать DMA, что после копирования необходимо инкрементировать адрес источника, чтоб копировать следующую точку изображения. Количество точек, копируемых за раз, влияет на скорость построения строки. Можно указать копирование сразу по 4 байта. Соответственно, копирование цвета глубиной 16 бит будет проходить в два раза быстрее. Однако объект должен иметь ширину, кратную двум, иначе в конце прорисованного объекта появится точка случайного цвета.

Итак, по указанным выше параметрам можно построить достаточное множество различных объектов. Далее мы рассмотрим, как ядро превратит прямоугольник в синусоиду (или другую фигуру).

Ядро подключается к процессу прорисовки каждый раз, когда начинается построение нового объекта, строки и кадра. Ядро проверяет каждый объект на предмет присутствия в данной строке. Задача простая: по координате и высоте объекта определить необходимость прорисовки в данной строке (координата строящейся строки — одна из переменных). Если прорисовка не требуется, проверяем аналогично следующий объект. Если прорисовка требуется, по номеру прорисовываемой строки и координатам объекта вычисляем адрес памяти, по которому начнем построение. Адрес источника копирования — это один из параметров объекта. Данные адреса — это готовые параметры для регистров DMA, заполняем их. Далее копируем последний параметр объекта «Управление DMA», что приводит к запуску этой периферии, то есть копированию объекта в строящуюся строку.

Когда началось копирование объекта в строящейся строке, можно изменять параметры его отображения для следующей строки. Например, мы отобразили в данной строке красный прямоугольник. Меняем цвет — значение по адресу памяти начала объекта. Тогда в следующей строке тот же самый прямоугольник будет уже другого цвета. Таким образом, цвет можно динамически менять от строки к строке и, например, получать градиентные переходы или просто многоцветные прямоугольники.

По окончании прорисовки кадра необходимо будет восстановить исходное значение цвета объекта (он должен меняться по строкам, но быть постоянным во времени, хотя никаких запретов нет). Аналогично можно менять любой другой параметр объекта. Например, можно линейно с номером строки уменьшать ширину рисуемого прямоугольника. В результате на экране будет трапеция или треугольник. Можно менять горизонтальную координату расположения прямоугольника, допустим, линейно, в зависимости от номера строки. Тогда получим параллелограмм на экране. Он может быть однотонным, а может быть картинкой из памяти. Можно задать массив параметров рисуемого объекта в зависимости от номера строки и задать там произвольные методы прорисовки. Например, можно задать таблицу горизонтальной координаты прорисовываемого объекта в виде синусоиды. Результат — на экране вертикальный график синусоиды с шириной, равной ширине заданного прямоугольника. Отличие работы ядра при прорисовке прямоугольника и синусоиды показано на рис. 9.

Работа ядра при отображении прямоугольника и синусоиды

Рис. 9. Работа ядра при отображении прямоугольника и синусоиды

Есть множество точек креатива в этом дизайне. Например, один и тот же объект можно отобразить несколько раз. По окончании прорисовки последней строки объекта можно изменить его вертикальную координату. В результате объект может появиться на экране еще раз. Именно таким образом построена горизонтальная сетка в проекте автора статьи. Горизонтальная сетка — это не 12 объектов, а один и тот же, отображенный 12 раз.

Загрузка ядра. Очевидно, что рассматриваемый дизайн требует частого подключения ядра: прерывания будут появляться после окончания прорисовки каждого объекта в строке, окончания выдачи строки и кадра по RGB-интерфейсу. Это, безусловно, скажется на производительной мощности контроллера. Тем не менее за время написания этого материала в проект была добавлена сенсорная резистивная панель на экране, управляемая тем же контроллером [1]. Что представляет собой добавка к проекту? Это работа с четырьмя портами, опрос АЦП по двум каналам и вычисление координат положения одного из объектов на экране. Нет никаких сомнений, что еще несколько подобных задач контроллер может выполнить без потери частоты кадров на экране.

Параметры получившегося проекта

Автору удалось добиться стабильной синхронизации и выдачи изображения на экран. Качество изображения при этом оказалось более чем достаточным для построения серийных приборов на базе этого приложения. Итак:

  • Объем кода: 15 кбит, в том числе объем картинок — 8 кбит.
  • Язык программирования — Си.
  • Параметры дисплея: 320×240 с глубиной цвета 16 бит.
  • Частота обновления: 10 кадров/с.
  • Количество отображаемых объектов — 9 (рис. 1):
    – фон;
    – красный график (динамически меняется);
    – желтый график (динамически меняется);
    – сетка вертикальная;
    – сетка горизонтальная;
    – логотип «Промэлектроника»;
    – надпись «T=»;
    – старший разряд цифровых показаний (динамически меняется);
    – младший разряд цифровых показаний (динамически меняется).
  • Загрузка ядра процессора — не измерялось (ожидается 50%).
  • Используется таймеров: 4 из 7 (7 — включая SysTick).
  • Используемое количество каналов обмена DMA — 2 из 7.
  • Используется одна микросхема внешней логики «2ИЛИ-НЕ».

Безусловно, получившийся проект является базой для построения законченных приложений. Однако, по мнению автора, архитектура проекта не оптимальна. Например, как оказалось, можно было бы отказаться от микросхемы внешней логики, которая предотвращала появление сигнала DEN во время процедуры вертикальной синхронизации. В программе оказалось востребованным определение момента окончания процедуры вертикальной синхронизации, соответственно, в этот момент можно разрешать выдачу DEN-сигнала, а запрещать — по окончании прорисовки экрана. Вполне разумным представляется отказ от 16-битного цвета в пользу 8-битного. Во-первых, это сэкономит память, во-вторых, почти в два раза ускорит внутренний обмен данных изображения при построении строки.

Почему в проекте реализована частота обновления всего 10 Гц? Изначально расчет показывал возможность обновления изображения указанного экрана более 30 Гц. Проблема была в скорости реакции DMA на запрос копирования. Данные по цвету рисуемой точки не успевали за тактами DCLK. Тем не менее частота 30 кадров/с вполне достижима, если применить контроллер STM32F103C4T6, который полностью совместим по выводам с STM32F100C4T6, но имеет тактовую частоту в три раза выше (72 МГц), и таймер 4, который потребуется использовать вместо таймера 15. Цена такого контроллера примерно в 2,5 раза выше, чем у примененного в проекте.

Литература

  1. http://forum.promelec.ru/index.php/topic,1856.0.html

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

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