Урок 34
Часть 3
Дисплей TFT 240×320 8bit
В прошлой части нашего урока мы написали ряд очень важных функций для работы с дисплеем, а также считали его идентификатор, что позволило нам стать уверенными в том, что мы с дисплеем нормально общаемся по 8-разрядной шине и что мы общаемся именно с тем дисплеем, который нам нужен.
Что ж, продолжим. Откроем файл ili9341.c и добавим в него две глобальные переменные для хранения ширины и высоты нашего дисплея в пикселях
#include «ili9341.h»
//—————————————————————
unsigned int X_SIZE = 0;
unsigned int Y_SIZE = 0;
unsigned long dtt=0;
Пока они у нас будут равны нулю, а значения мы им присвоим в процессе инициализации.
Создадим функцию изменения ориентации дисплея
//—————————————————————
void TFT9341_SetRotation(unsigned char r)
{
}
//—————————————————————
У нас будет четыре вида ориентации. Два вертикальных — один обычный, один перевёрнутый и подобные два горизонтальных. Условимся обозначать из следующим образом:
0 — вертикальная обычная ориентация
1 — горизонтальная обычная ориентация
2 — вертикальная перевёрнутная ориентация
3 — горизонтальная перевёрнутная ориентация.
Теперь начнём писать тело нашей функции.
Посмотрим в даташите регистр 0x36
Как мы видим в нотации к данному регистру, что мы можем менять ориетнацию в зависимости от состояния определённых битов в параметре.
Поэтому сначала отправим адрес регистра в контроллер дисплея, а затем создадим ветвление в зависимости от вызываемого режима ориентации
void TFT9341_SetRotation(unsigned char r)
{
TFT9341_SendCommand(0x36);
switch(r)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
}
Теперь отправим параметр. Содержимое его будет зависеть от определённых битов ориентации. Биты MH и ML всегда будут в нуле, BGR всегда в единице, а вот значение битов MV, MX и MY будут меняться.
При обычной вертикальной ориентации (входной параметр ноль) в единице из этих трёх битов будет только MX (Column Address Order).
Поэтому напишем первый кейс следующим образом, заодно и присвоим нашим глобальным переменным размеров экрана соответствующие значения
case 0:
TFT9341_SendData(0x48);
X_SIZE = 240;
Y_SIZE = 320;
break;
При горизонтальной ориентации (входной параметр 1) в единице будет бит MV (Row / Column Exchange).
Напишем следующий кейс
case 1:
TFT9341_SendData(0x28);
X_SIZE = 320;
Y_SIZE = 240;
break;
При вертикальной перевёрнутой ориентации (входной параметр 2) в единице будет уже бит MY (Row Address Order).
Напишем кейс
case 2:
TFT9341_SendData(0x88);
X_SIZE = 240;
Y_SIZE = 320;
break;
При горизонтальной перевёрнутой ориентации (входной параметр 3) в единице будут все три бита
case 3:
TFT9341_SendData(0xE8);
X_SIZE = 320;
Y_SIZE = 240;
break;
Продолжим нашу инициализацию. Допишем в функцию инициализации следующий код, который лишний раз перезагрузит программно наш дисплей, а вернее его контроллер
str_lcd(str);
TFT9341_SendCommand(0x01);//Software Reset
Следующая команда уже будет требовать данные (целых 5 параметров)
TFT9341_SendCommand(0x01);//Software Reset
TFT9341_SendCommand(0xCB);//Power Control A
TFT9341_SendData(0x39);
TFT9341_SendData(0x2C);
TFT9341_SendData(0x00);
TFT9341_SendData(0x34);
TFT9341_SendData(0x02);
Ну, я не буду сюда постить весь даташит, дабы не засорять страницу и базу данных, буду объяснять вкратце.
Данный регистр, в которые мы отправили столько данных — это регистр настроек или управления. Все биты, которые мы там включили, вы можете посмотреть в даташите.
Есть ещё один подобный регистр, в который мы отправим три аргумента
TFT9341_SendData(0x02);
TFT9341_SendCommand(0xCF);//Power Control B
TFT9341_SendData(0x00);
TFT9341_SendData(0xC1);
TFT9341_SendData(0x30);
Следующие 2 команды вносят настройки в регистр управления различными таймингами
TFT9341_SendData(0x30);
TFT9341_SendCommand(0xE8);//Driver timing control A
TFT9341_SendData(0x85);
TFT9341_SendData(0x00);
TFT9341_SendData(0x78);
TFT9341_SendCommand(0xEA);//Driver timing control B
TFT9341_SendData(0x00);
TFT9341_SendData(0x00);
Также заполним ещё ряд регистров, назначения которых я объяснил в комментариях к каждой команде. Также где-то посередине кода мы вызовем функцию ориентации дисплея и инициализируем там обычный вертикальный режим с индексом 0. На этом этапе у нас и проинициализируются наши глобальные переменные размера нашего экрана
TFT9341_SendData(0x00);
TFT9341_SendCommand(0xED);//Power on Sequence control
TFT9341_SendData(0x64);
TFT9341_SendData(0x03);
TFT9341_SendData(0x12);
TFT9341_SendData(0x81);
TFT9341_SendCommand(0xF7);//Pump ratio control
TFT9341_SendData(0x20);
TFT9341_SendCommand(0xC0);//Power Control 1
TFT9341_SendData(0x10);
TFT9341_SendCommand(0xC1);//Power Control 2
TFT9341_SendData(0x10);
TFT9341_SendCommand(0xC5);//VCOM Control 1
TFT9341_SendData(0x3E);
TFT9341_SendData(0x28);
TFT9341_SendCommand(0xC7);//VCOM Control 2
TFT9341_SendData(0x86);
TFT9341_SetRotation(0);
TFT9341_SendCommand(0x3A);//Pixel Format Set
TFT9341_SendData(0x55);//16bit
TFT9341_SendCommand(0xB1);
TFT9341_SendData(0x00);
TFT9341_SendData(0x18);// Частота кадров 79 Гц
TFT9341_SendCommand(0xB6);//Display Function Control
TFT9341_SendData(0x08);
TFT9341_SendData(0x82);
TFT9341_SendData(0x27);//320 строк
TFT9341_SendCommand(0xF2);//Enable 3G (пока не знаю что это за режим)
TFT9341_SendData(0x00);//не включаем
TFT9341_SendCommand(0x26);//Gamma set
TFT9341_SendData(0x01);//Gamma Curve (G2.2) (Кривая цветовой гаммы)
TFT9341_SendCommand(0xE0);//Positive Gamma Correction
TFT9341_SendData(0x0F);
TFT9341_SendData(0x31);
TFT9341_SendData(0x2B);
TFT9341_SendData(0x0C);
TFT9341_SendData(0x0E);
TFT9341_SendData(0x08);
TFT9341_SendData(0x4E);
TFT9341_SendData(0xF1);
TFT9341_SendData(0x37);
TFT9341_SendData(0x07);
TFT9341_SendData(0x10);
TFT9341_SendData(0x03);
TFT9341_SendData(0x0E);
TFT9341_SendData(0x09);
TFT9341_SendData(0x00);
TFT9341_SendCommand(0xE1);//Negative Gamma Correction
TFT9341_SendData(0x00);
TFT9341_SendData(0x0E);
TFT9341_SendData(0x14);
TFT9341_SendData(0x03);
TFT9341_SendData(0x11);
TFT9341_SendData(0x07);
TFT9341_SendData(0x31);
TFT9341_SendData(0xC1);
TFT9341_SendData(0x48);
TFT9341_SendData(0x08);
TFT9341_SendData(0x0F);
TFT9341_SendData(0x0C);
TFT9341_SendData(0x31);
TFT9341_SendData(0x36);
TFT9341_SendData(0x0F);
Выйдем из спящего режима и включим дисплей
TFT9341_SendData(0x0F);
TFT9341_SendCommand(0x11);//Выйдем из спящего режим
_delay_ms(150);
TFT9341_SendCommand(0x29);//Включение дисплея
TFT9341_SendData(0x2C);
_delay_ms(150);
}
На этом инициализация закончена.
В следующей части нашего занятия мы напишем ещё несколько функций для работы с дисплеем и попробуем залить экран определенным цветом.
Предыдущая часть Программирование МК AVR Следующая часть
Техническая документация на контроллер дисплея ILI9341
Программатор, символьный дисплей LCD 20×4 и переходник для него можно приобрести здесь:
Программатор USBASP USBISP с адаптером USBASP USBISP 3.3 с адаптером
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Посмотрел инициализацию дисплея, есть замечания.
1. TFT9341_SendCommand(0xB6);//Display Function Control
Команде необходимы 4 параметра.
2. TFT9341_SendCommand(0xF2);//Enable 3G (пока не знаю что это за режим)
Отключена по умолчанию.
3. TFT9341_SendCommand(0x29);//Включение дисплея
TFT9341_SendData(0x2C);
_delay_ms(150);
Команда без параметров.
У меня не совсем корректно выполняются примеры, которые Вы рассматриваете в следующих частях урока, поэтому решил посмотреть инициализацию. Удачи!
У меня тоже Ваш пример в Proteus не рабоает. Работает все, что до заливки прямоугольников. Дальше — ничего.