Инициализация TFT дисплея на примере SSD1289 для AVR.
На днях пришёл TFT дисплей, заказанный на али, давайте рассмотрим его основные характеристики.
Основные характеристики дисплея:
В качестве управляющего микроконтроллера возьмем Atmega16. Готовые примеры инициализации искать не стал, решил разобраться как он работает и написать свою. Для начала разберёмся с интерфейсом подключения. Общение с контроллером SSD1289 может происходить по 1 из 4 интерфейсов: i8080, M6800, RGB, SPI, но чтобы мы не мучились, не зная какой выбрать, производитель модуля помог нам. Он оставил на выбор два 16 битных интерфейса: интеловский i8080 и мотороловский M6800. i8080 и M6800 — параллельные интерфейсы, которые могут работать в 18/16/8-разрядном режиме. Выбор пал на i8080, хотя судя по даташиту он отличается от M6800 только тем, что у i8080 сигналы записи (WR) и чтения (RD) раздельные, а у M6800 же сигнал управления направлением RD/WR один, но дополнительно к нему есть сигнал разрешения E.
Теперь давайте посмотрим на распиновку модуля.
Выводы питания.
VCC – напряжение питания модуля. Внутри модуля находится стабилизатор напряжения на 3.3V, от которого питаются графический контроллер(SSD1289), контроллер резистивного сенсорного экрана(XPT2046) и SD карта. Наличие стабилизатора позволяет подавать на модуль питание равное 5V. Но обмен информацией между микроконтроллером и модулем должен проходить с помощью 3.3V. У меня в схеме модуль и микроконтроллер питаются одним напряжением — 3.3V, что обеспечивает нормальный обмен данными.При таком напряжении питания микроконтроллер нормально работает на частоте 8MHz. Да, кстати, я подавал 5 вольт на микроконтроллер и модуль, мне повезло ничего не сгорело и все работало, но так делать не стоит.
GND – общий вывод (земля).
LED-A – анод подсветки TFT дисплея, необходимо подключать через токоограничивающий резистор, при питании 3,3V подключил через 200 Оhm.
Выводы управления графическим контроллером.
[DB15, DB0] (Data Bus) – 16-разрядная шина данных/команд.
RS (Register Select) –пин с помощью которого можно переключаться между регистрами данных (GRAM) и регистрами команд (Instruction Registers), в даташите он называется D/C.
WR (Write) – строб записи данных/команд.
RD (Read) – строб чтения данных/параметров.
REST (Reset) – сброс графического контроллера.
CS (Chip Select) – активация/дезактивация графического дисплея.
Общая схема подключения TFT дисплея изображена ниже.
Теперь надо разобраться как отправить SSD1289 команды/данные, для этого давайте посмотрим на картинку ниже.
На картинке видно, что это можно сделать двумя способами, мы реализуем первый.
Для того чтобы отправить команду надо выполнить следующую последовательность действий:
Для того чтобы отправить данные надо выполнить следующую последовательность действий:
Ниже реализация отправки команд/данных на С.
С подключением разобрались теперь переходим к инициализации. Открываем даташит и находим странницу, на которой описан порядок инициализации.
Для того чтобы инициализировать контроллер SSD1289 надо записать в регистр R07, значение 0021h , выставив, таким образом, GON = 1, DTE = 0, D[1:0] = 01, что делают эти биты рассматривать не будем, пока это значения не имеет.
На следующем шаге включаем тактирование, установив в регистр R00 значение 0001h. Кстати, если после инициализации прочесть данные с этого регистра, в случае успешной инициализации должно вернуться 8989h.
Далее, снова возвращаемся в R07 и устанавливаем значение 0023h.
Следующим шагом выходим из спящего режима, устанавливая в R10 значение 0000h.
Ждём 30 миллисекунд. Устанавливаем в регистр R07 значение 0033h. Далее, в регистр R11 устанавливаем значение 6838h, давайте рассмотрим, что означают эти цифры.
POR - это значение по умолчанию и оно равно 6830h. Значит, по умолчанию дисплей может отображать 65K цветов, за это отвечает первая цифра 6 в значении 6830h, это надо запомнить так дальше при формировании цвета мы к этому ещё вернёмся.
Дальше мы определяем порядок записи точек, дело в том, что нам для вывода изображения достаточно выставить координаты только первой точки, далее, надо отправлять SSD1289 только цвет следующей точки, а он сам будет её отрисовывать по алгоритму, который мы сейчас выберем. И вот здесь, точно сказать почему нельзя, при таких настройках включился режим, отмеченный зелёным кружком, а должен был включиться отмеченный красным.
Значение в регистре R02 оставим по умолчанию и на этом закончим инициализацию.
Теперь все то, что рассмотрели оформим в виде кода.
Если последовательно выполнить все описанные действия, в случае успешной инициализации, экран хаотично раскраситься разноцветными точками, как на фото ниже.
Теперь мы знаем как инициализировать TFT дисплей на котором установлен контроллер SSD1289, в следующей статье мы рассмотрим как выводить отдельные символы и писать строки. Также в конце следующей статьи можно скачать пример для Atmel Studio 6.2.
P.S там где покупал дисплей больше не продают, в комментариях Андрей оставил ссылку на дисплей, который у него запустился, чтобы не искать, оставлю её тут.
Display_ebay
P.S.S для желающих быстро проверить работает ли их дисплей, оставляю тут прошивку для Atmega16
Основные характеристики дисплея:
- 3,2 дюйма, с разрешением 320х240
- драйвер TFT дисплея - SSD1289, драйвера сенсорной панели - XPT2046
- управление TFT по протоколу 6800, 8080, поддержка FSMC
- интерфейс управления сенсорной панелью SPI
- напряжение питания 5V или 3.3V, благодаря встроенному понижающему стабилизатору
- возможность управления подсветкой с помощью ШИМ
- встроенный разъем для SD card
- свободное место для пайки FLASH памяти
- поддерживает горизонтальную и вертикальную ориентацию, возможность отображения нескольких окон
- глубина цвета: 18бит (262 144 комбинаций)
В качестве управляющего микроконтроллера возьмем Atmega16. Готовые примеры инициализации искать не стал, решил разобраться как он работает и написать свою. Для начала разберёмся с интерфейсом подключения. Общение с контроллером SSD1289 может происходить по 1 из 4 интерфейсов: i8080, M6800, RGB, SPI, но чтобы мы не мучились, не зная какой выбрать, производитель модуля помог нам. Он оставил на выбор два 16 битных интерфейса: интеловский i8080 и мотороловский M6800. i8080 и M6800 — параллельные интерфейсы, которые могут работать в 18/16/8-разрядном режиме. Выбор пал на i8080, хотя судя по даташиту он отличается от M6800 только тем, что у i8080 сигналы записи (WR) и чтения (RD) раздельные, а у M6800 же сигнал управления направлением RD/WR один, но дополнительно к нему есть сигнал разрешения E.
Теперь давайте посмотрим на распиновку модуля.
Выводы питания.
VCC – напряжение питания модуля. Внутри модуля находится стабилизатор напряжения на 3.3V, от которого питаются графический контроллер(SSD1289), контроллер резистивного сенсорного экрана(XPT2046) и SD карта. Наличие стабилизатора позволяет подавать на модуль питание равное 5V. Но обмен информацией между микроконтроллером и модулем должен проходить с помощью 3.3V. У меня в схеме модуль и микроконтроллер питаются одним напряжением — 3.3V, что обеспечивает нормальный обмен данными.При таком напряжении питания микроконтроллер нормально работает на частоте 8MHz. Да, кстати, я подавал 5 вольт на микроконтроллер и модуль, мне повезло ничего не сгорело и все работало, но так делать не стоит.
GND – общий вывод (земля).
LED-A – анод подсветки TFT дисплея, необходимо подключать через токоограничивающий резистор, при питании 3,3V подключил через 200 Оhm.
Выводы управления графическим контроллером.
[DB15, DB0] (Data Bus) – 16-разрядная шина данных/команд.
RS (Register Select) –пин с помощью которого можно переключаться между регистрами данных (GRAM) и регистрами команд (Instruction Registers), в даташите он называется D/C.
WR (Write) – строб записи данных/команд.
RD (Read) – строб чтения данных/параметров.
REST (Reset) – сброс графического контроллера.
CS (Chip Select) – активация/дезактивация графического дисплея.
Общая схема подключения TFT дисплея изображена ниже.
Теперь надо разобраться как отправить SSD1289 команды/данные, для этого давайте посмотрим на картинку ниже.
На картинке видно, что это можно сделать двумя способами, мы реализуем первый.
Для того чтобы отправить команду надо выполнить следующую последовательность действий:
- на ножке D/C выставляем ноль говорим, что будем слать команду
- на ножке RD выставляем единицу, чтобы точно записывать
- активируем чип, устанавливая на ножке CS нуль
- выдаем на шину данные, в нашем случае это два порта
- на ножке WR выставляем единицу
- ждем несколько микросекунд
- на ножке WR выставляем нуль
- на ножке CS выставляем единицу, деактивируем чип
Для того чтобы отправить данные надо выполнить следующую последовательность действий:
- на ножке D/C выставляем единицу говорим, что будем слать данные
- на ножке RD выставляем единицу, чтобы точно записывать
- активируем чип, устанавливая на ножке CS нуль
- выдаем на шину данные, в нашем случае это два порта
- на ножке WR выставляем единицу
- ждем несколько микросекунд
- на ножке WR выставляем нуль
- на ножке CS выставляем единицу, деактивируем чип
Ниже реализация отправки команд/данных на С.
#define D0 PORTA //так данные передаются по 16 битной шине,
#define D7 PORTD //под это дело мы используем два порта
#define COMMAND_PORT PORTB //управляющий порт
#define lcd_dc 0 //так же может называться RS(comm - 0; data - 1)
#define lcd_res 1 //(active - 0)
#define lcd_rd 2 //(read_active - 0)
#define lcd_cs 3 //(chip_select_active - 0)
#define lcd_wr 5 //(write_active - 0)
void Lcd_Write_Index(uint16_t index)
{
COMMAND_PORT &= ~(1<<lcd_dc); //будем слать команду
COMMAND_PORT |= (1<<lcd_rd); //выставляем на ножке, отвечающей за чтение 1
COMMAND_PORT &= ~(1<<lcd_cs); //активируем чип
D0 = (index & 0X00FF); //через D0 шлем младший байт
D7 = (index & 0XFF00)>>8; //затем через D7 старший
COMMAND_PORT &= ~(1<<lcd_wr); //теперь стробируем битом записи
_delay_us(5);
COMMAND_PORT |= (1<<lcd_wr);
COMMAND_PORT |= (1<<lcd_cs); //деактивируем чип
}
////////////////////////
void Lcd_Write_Data(uint16_t data) //все то же самое только DC устанавливаем в единицу
{
COMMAND_PORT |= (1<<lcd_dc) ;
COMMAND_PORT |= (1<<lcd_rd);
COMMAND_PORT &= ~(1<<lcd_cs);
D0 = (data & 0X00FF);
D7 = (data & 0XFF00)>>8;
COMMAND_PORT &= ~(1<<lcd_wr);
_delay_us(5);
COMMAND_PORT |= (1<<lcd_wr);
COMMAND_PORT |= (1<<lcd_cs);
}
/////////////для записи данных в регистры напишем простенькую функцию
void Lcd_Write_Reg(uint16_t lcd_reg, uint16_t lcd_data)
{
COMMAND_PORT &= ~(1<<lcd_cs);
Lcd_Write_Index(lcd_reg);
Lcd_Write_Data(lcd_data);
COMMAND_PORT |= (1<<lcd_cs);
}
С подключением разобрались теперь переходим к инициализации. Открываем даташит и находим странницу, на которой описан порядок инициализации.
Для того чтобы инициализировать контроллер SSD1289 надо записать в регистр R07, значение 0021h , выставив, таким образом, GON = 1, DTE = 0, D[1:0] = 01, что делают эти биты рассматривать не будем, пока это значения не имеет.
На следующем шаге включаем тактирование, установив в регистр R00 значение 0001h. Кстати, если после инициализации прочесть данные с этого регистра, в случае успешной инициализации должно вернуться 8989h.
Далее, снова возвращаемся в R07 и устанавливаем значение 0023h.
Следующим шагом выходим из спящего режима, устанавливая в R10 значение 0000h.
Ждём 30 миллисекунд. Устанавливаем в регистр R07 значение 0033h. Далее, в регистр R11 устанавливаем значение 6838h, давайте рассмотрим, что означают эти цифры.
POR - это значение по умолчанию и оно равно 6830h. Значит, по умолчанию дисплей может отображать 65K цветов, за это отвечает первая цифра 6 в значении 6830h, это надо запомнить так дальше при формировании цвета мы к этому ещё вернёмся.
Дальше мы определяем порядок записи точек, дело в том, что нам для вывода изображения достаточно выставить координаты только первой точки, далее, надо отправлять SSD1289 только цвет следующей точки, а он сам будет её отрисовывать по алгоритму, который мы сейчас выберем. И вот здесь, точно сказать почему нельзя, при таких настройках включился режим, отмеченный зелёным кружком, а должен был включиться отмеченный красным.
Значение в регистре R02 оставим по умолчанию и на этом закончим инициализацию.
Теперь все то, что рассмотрели оформим в виде кода.
#define lcd_res 1 //(active - 0)
void Init()
{
_delay_ms(100); //не большая задержка после включения
COMMAND_PORT |= (1<<lcd_res); //устанавливаем reset в 1, чтобы включился SSD1289
Lcd_Write_Reg(0X0007, 0X0021); //далее записываем в регистры значения
Lcd_Write_Reg(0X0000, 0X0001);
Lcd_Write_Reg(0X0007, 0X0023);
Lcd_Write_Reg(0X0010, 0X0000);
_delay_ms(30);
Lcd_Write_Reg(0X0007, 0X0033);
Lcd_Write_Reg(0X0011, 0X6838);
Lcd_Write_Reg(0X0002, 0X0600);
}
Если последовательно выполнить все описанные действия, в случае успешной инициализации, экран хаотично раскраситься разноцветными точками, как на фото ниже.
Теперь мы знаем как инициализировать TFT дисплей на котором установлен контроллер SSD1289, в следующей статье мы рассмотрим как выводить отдельные символы и писать строки. Также в конце следующей статьи можно скачать пример для Atmel Studio 6.2.
P.S там где покупал дисплей больше не продают, в комментариях Андрей оставил ссылку на дисплей, который у него запустился, чтобы не искать, оставлю её тут.
Display_ebay
P.S.S для желающих быстро проверить работает ли их дисплей, оставляю тут прошивку для Atmega16
Похожие статьи