Параллельный интерфейс 8080 для TFT 3,2 inch 320×240

Преамбула…
Мне совершенно непонятна ценовая политика производителей ЖК-дисплеев. Я думал, что это наши интернет-магазины лупят такие цены за винстаровские монохромники. Однако прогулки по тому же ебею показывают подобное положение дел и «у них». Самый дешёвый 128х64 стоит примерно столько же или больше, чем цветной 320х240  с тачскрином, SD-картой и другими плюшками. А винстаровский 320х240 стоит вообще заоблачных денег!!! Поэтому для очередных поделок выбор был сделан в пользу NEW 3.2″ TFT LCD Module+Touch Panel+ PCB Adapter(with SD + Micro SD card cage)

Дисплей всем хорош, только в сети почему-то практически нет его описания. То есть  на подобные мониторчики на основе SSD1289 информации хватает, но там несколько другие исполнения в железе. Кроме того, когда начал изучать его даташит упомянутого контроллера дисплея, обратил внимание на почти стопроцентную схожесть с дисплеем uDisp320240 на основе SSD2119, который я ковырял в некоторых направлениях здесь. Проверил — точно, даташиты практически идентичные. Однако отличия всё же есть. Прежде всего в некоторых разрядах некоторых регистров (см. даташиты).

Быстрый старт…
Рассматриваемый дисплей работает только с параллельным 18-ти разрядным интерфейсом 8080, в отличие от того же uDisp320240, где вариантов довольно много. Вернее сказать так: в конкретном исполнении дисплея его контроллер работает с 18-ти разрядным параллельным интерфейсом. Для этого внутри запаяны соответствующие перемычки, а наружу выведены необходимые выводы. Ну да и ладно — зато работать будет быстрее. Как я уже упоминал выше, беглое сравнение регистров управления, а также последовательности команд включения/выключения упорно наталкивало меня на мысль об идентичности контроллеров. И я пошёл по пути меньшего сопротивления. Взял исходники отсюда и переписал только функции записи команд/данных. Параллельный интерфейс хорош своей простотой. Эпюры можно посмотреть в даташите Figure 13-2 –Parallel 8080-series Interface Timing Characteristics, причём в двух вариантах. Отличаются варианты между собой только тем, что в первом команда стробируется сигналом WR или RD (в зависимости от производимого действия ЗАПИСЬ/ЧТЕНИЕ), в во втором — сигналом CS. Порядок ногодрыгания ИМХО из рисунка, думаю, понятен всем. Быстро написал две быдлофункции 🙂

void write_command (unsigned char command)
{   
    PORT_data_L = command;//выставили команду на шину
    PORT_data_H = 0x00;//
    PORT_command &= ~(1<<RS);//дрыгаем
    PORT_command |=  (1<<WR) | (1<<RD) | (1<<CS);//ногами
    PORT_command &= ~(1<<WR);//согласно
    PORT_command &= ~(1<<CS);//даташита
    asm("nop");asm("nop");asm("nop");asm("nop");//длительность строба
    PORT_command |=  (1<<CS);//
    PORT_command |=  (1<<WR);//
    PORT_data_L = 0x00;//
    PORT_data_H = 0x00;//
}
 
void write_data (unsigned int data)
{
    PORT_data_L = (unsigned char)(data & 0x00FF);//выставили младший байт данных
    PORT_data_H = (unsigned char)(data>>8);//старший байт данных
    PORT_command |=  (1<<RS);//дрыгаем
    PORT_command |=  (1<<WR) | (1<<RD) | (1<<CS);//ногами
    PORT_command &= ~(1<<WR);//согласно
    PORT_command &= ~(1<<CS);//даташита
    asm("nop");asm("nop");asm("nop");asm("nop");//длительность строба
    PORT_command |=  (1<<CS);//
    PORT_command |=  (1<<WR);//
    PORT_data_L = 0x00;//
    PORT_data_H = 0x00;//
}

Как видите они практически идентичны, и, естественно, их стоило бы  уменьшить, написав одну вспомогательную функцию — общую часть для команды/данных. Но мне было лень. Конечно же сделал инициализацию портов, соответственно назначениям в дефайнах (см. исходник). В качестве управляющего контроллера использовал ATmega8515. Его микроконтроллерный модуль с дисплеем соединил купленными недавно на деалэкстриме проводами. Собрал в кучу код, скомпилировал и залил в кристалл. Ура! Получилось! (Это выполнение функции show_all_simbols). Но… Как-то не так. Нетрадиционная ориентация в пространстве.

Курение даташита… Исправление кода…
Первое, что бросается в глаза — координаты здесь «неправильные».Горизонталь  «X» — узкая 240-точечная , а вертикаль «Y» — широкая 320-точечная сторона. Соответственно, текст «пропечатывается » справа налево, и матрицы, составляющие символы (читаем тут) , выводятся так же неправильно. Для исправления неправильной «ориентации» было сделано следующее:
1) Изменено значение сочетания разрядов ID1, ID0, AM регистра R11hотвечающих за направление изменения адреса видеопамяти, при записи туда (в видеопамять) данных. Несмотря на витиеватость фразы сложностей тут никаких (см. рисунок ниже).
Сейчас у нас при записи любого значения в видеопамять (для отображения пикселя) адрес видеопамяти автоматически увеличивается (ID0=1) по горизонтали X (AM=0). После записи пикселей по горизонтали X (т.е. после прохождения адреса конца горизонтали)  адрес видеопамяти по вертикали Y также увеличивается (ID1=1). Такая настройка (она же по умолчанию) на рисунке обведена красным фломастером.
Нам же нужна настройка при которой после записи в видеопамять адрес по горизонтали X будет уменьшаться (ID0=0), а, после прохождения нуля по горизонтали X (т.е. после записи всех пикселей в строке) увеличится по вертикали Y (ID1=1). Такая настройка на рисунке обведена зелёным маркером. Для её реализации  в регистр R11 нужно записать не дефолтное значение 0х6830, а новое — 0х6820.
Примечание: вышеуказанный рисунок (взят из даташита) выполнен неудачно в плане визуального восприятия координат ИМЕННО этой модели дисплея. Горизонталь указана шире вертикали, а также ноль координат по горизонтали обозначен слева, а не справа, как оно есть на самом деле. Думаю, что это связано с большой номенклатурой выпускаемых дисплеев и нежеланием переделывать документацию под каждую модель.
2) Изменена функция вывода всех символов

//Функция вывода всех символов заданного размера и цвета на выбранном фоне
void show_all_simbols (unsigned char size,unsigned int color,unsigned int phone)
{
    unsigned char max_x,max_y,x,y,k=0;//количество знакомест по х и у (зависит от размера символов), счётчик символов
 
	if(size > 5) size=5;//размер точки более 5х5 пикселей нецелесоообразен
	max_y = 320/(size*8);//определяем кол-во знакомест по x
	max_x = 240/(size*8);//определяем кол-во знакомест по y
 
    for(y=0; y < max_y; y++)//по Y 
    {   
        for(x=max_x; x > 0; x--)//по X 
	{
	   simbol((x*8*size - 1),y*8*size,color,phone,simbols+k*8,size);//выводим символы заданных параметров
	   if(k++ > 94) return;//выход из функции при переборе всех символов
	}
    }
}

в плане адресации по горизонтали X (см. код)

Некоторые пояснения к схеме…
Я подключал дисплей к микроконтроллерному модулю, имея на руках только распиновку разъёма. Она приведена на странице продукта внизу (имею в виду сайт ebay). С линиями непосредственно интерфейса вопросов нет. По питанию имеются выводы +5В и +3,3В. Подключив к +5В источник, я на выводе +3,3В наблюдал указанное  напряжение, и сделал вывод, что где-то внутри находится стабилизатор. Исходя из этого,с вывода +3,3В я подал питание на микроконтроллерный модуль. Предположение оказалось верным. В этом я убедился, ознакомившись со схемой дисплея.
Вывод LCD_BK  (разрешение подсветки) можно никуда не подключать — по дефолту он висит на питании, «разрешая» подсветку. Схему, даташит на контроллер ssd1289, примеры кода для с51 (которые мне не понадобились, но может ещё пригодятся) я выпросил у продавца. Да, кстати, на вывод +5В можно смело подавать +3,3В — дисплей работает без сбоев!

Медленный старт…
В результате вышеуказаных действий я вывел на экран нормально ориентированное изображение (изменил цвет шрифта для лучшей контрастности).
Кроме того проверил работу по отображению точек, простейшей графики — всё отлично работает без изменений в функциях!

Совет:
При применении в своих конструкциях описанной разработки всегда обращайте внимание на правильную адресацию выводимых изображений.

Удачи, господа коллеги!

UPDATE 28.11.2012:
Выложил исходник для обобщения поданного материала.

Запись опубликована в рубрике Комплектующие с метками . Добавьте в закладки постоянную ссылку.

14 комментариев: Параллельный интерфейс 8080 для TFT 3,2 inch 320×240

  1. Иван говорит:

    Очень полезная статья!!!
    Можно ли прикрепить к статье исходники ? Думаю это ускорит повторение схемы и устройства в целом. Заранее благодарен за Ваше понимание.

  2. s_black говорит:

    Добавил исходник. Удачи, друзья!

  3. Иван говорит:

    А работа с тачскрином аналогична с дисплеем http://www.embed.com.ua/mikrokontrollernyiy-konstruktor/tft-udisp320240-chast-3/

  4. s_black говорит:

    На указанном выше дисплее установлен контроллер резистивного тачскрина ADS7843. На колодку выведены его выводы для обмена по SPI. Разберусь с его работой — выложу статью.

  5. Иван говорит:

    Скиньте пожалуйста схему подключения выводов D0-D15, а то мне не понятно, где младший порт а где старший порт (Порт А, порт С), где младший разряд а где старший разряд.

  6. s_black говорит:

    PA15 — D15, PC0 — D0

  7. Иван говорит:

    PA7 — D15, PC0 — D0 ?

  8. Иван говорит:

    какая к вас частота кварца для МК ?

  9. s_black говорит:

    Внутренний RC 4 MHz.

  10. Иван говорит:

    есть проблемы с отображением строк, они отображаются справа налево. Или возможно это так только у меня.

  11. s_black говорит:

    Вы статью внимательно читали??? Там же речь об этом и идет!

  12. Иван говорит:

    Дисплей запустил. Спасибо.
    Только есть нюансы. Запускал на контролере mega16, а он нестабильно работает при частоте 12МГц на напряжении 3.3 В. Поэтому пришлось применить 5В. Сигналы управления подаются на дисплей величиной 5В (не знаю правильно ли это, но работает). Также запустил тачскрин (через SPI), при этом я переориентировал дисплей. Сделал инкрементацию по оси х и y, так проще при работе с ним. Еще поправил инициализацию дисплея, установки цветов. В результате поднял частоту кадров, и исправил цвета, было BGR, а стало RGB. В результате стало возможным выводить куски изображения.

  13. s_black говорит:

    Это есть гут ! Я вот тоже сейчас с видеокамеры OV7670 картинку на этот дисплей пробую выводить.

  14. kentik говорит:

    а какие изменения для 8-ми битного интерфейса?

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

Ваш e-mail не будет опубликован.