Драсти всем!!! Давайте для начала я начну с начала. На “старом” форуме просил помощи в освоении оного, но, не найдя поддержки, по понятным причинам, пришлось самому. Короче для тех кто делает первые шаги…
Лет пять назад заказал на Ali такой экранчик. Вот, дошли руки. Ещё лет уже 10 назад, случайно заказал шилд для arduino mega 2560 (далее mega). Раскачивать такой экран на mega я считаю не совсем правильным. Уж слишком медленный для такого разрешения. Надо отдать должное разрoбртчикам платки arduino Due (далее Due) за максимальную адаптацию. Забегу наперёд: тестировал дисплей на обеих платах (Mega и Due) о чём далее.
Начинаем…
Собираем этот “бутерброд” Mega/Due + Shield 2.2 + SSD1963.
Открываем пример из библиотеки UTFT Demo 800x480.
Подправляем инициализацию дисплея на следующую:
UTFT myGLCD(TFT01_70, 38, 39, 40, 41);
Ну в принципе и всё. Далее фантазируем как надо. Экран зажёгся и показывает.
Для Mega и Due тут всё одинаковое.
Далее нам нужно укротить Touch идущий в комплекте. На нашу радость Touch реализован через микросхемку преобразователя и обращаемся мы уже с сенсору в цифровом виде. Не нужно “дёргать” аналоговые пины и читать чё у них там. Сразу оговорюсь что на Mega сернсор запустить не получилось и не стал тратить время так как в итоге мой SSD будет работать на Due. Для инициализации раскоментирываем следующее из любого примера…
#include <URTouch.h>
URTouch myTouch( 6, 5, 4, 3, 2);
само собой подключив библиотеку URTouch, установив предварительно.
Если мы видим что всё заработало, запускаем пример калибровки. Он вроде там описан. Только в примере указана ориентация как портретная т.е. вертикальная. Если планируется использовать как альбомную, сразу нужно подправить в примере и выбрать нужную…
#define TOUCH_ORIENTATION PORTRAIT // Портретная (вертикальная) ориентация
#define TOUCH_ORIENTATION LANDSCAPE // Ландшафтная (горизонтальная) ориентация
Следуйте инструкциям и для калибровки используйте что то в виде стилуса (НЕ ПАЛЬЦЫ) после чего откройте файл URTouchCD.h и внеся изменения, сохраните.
Теперь добрались мы и до карты памяти. Заявляется что под UTFT есть специально обученная библиотека UTFT_SdRaw . Т.к. я уже работал с такой библиотекой, ничего изобретать не стал и подключил библиотеку SdFat.h (в чём разница не знаю). Хотя с картой памяти всё интересней. Тут Mega оказалась более работоспособней. Шилд версии 2.2 всё ж под неё ваялся. Соответственно SPI интерфейс для SD карты подключён на аппаратный SPI Mega. Начнём с неё.
Подключаем библиотеку “SdFat.h”.
Объявляем-заявляем всё что надо…
Пин Chip selekt оставляем SS (на Mega это пин 53)
Подправляем частоту тактирования на 16 МГц.
Получаем такое…
#include "SdFat.h"
SdFat SD;
File Myfile;
const uint8_t SD_CS_PIN = SS;
#define SPI_CLOCK SD_SCK_MHZ(16)
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
В Сетапе инициализируем примерно так…
SD.begin(SD_CONFIG);
Я конечно не знаю кому для чего нужна SD карта, но мне с неё нужно выводить изображения /raw формата (ну как raw, с натяжкой), поэтому нужно постараться чтоб в примерах найти как проверить работает ли карта. В примерах SdFat можно запустить пример OpenNext, подправив частоту тактирования, и в порту посмотреть содержание карты памяти. Советую поместить туда несколько файлов, ко которым станет понятно работает карта или нет.
Теперь что касается карты памяти и Due. Тут надо немного колхозить т.к. аппаратный SPI у Due не совсем там же. Точнее совсем не там же. По по монтажной схеме ищем SPI, выпаиваем пины 50, 51, 52 на шилде и подключаем удобным способом к Due. Что касается пина Chip Selekt , на Due это пин 10, но так как уже много пинов с аппаратным ШИМ и так заняты (со 2 по 6) ТочСкрином, то ШИМ пины уже почти на вес золота. По этому просто рекомендую пин 53 не трогать и при инициализации Карты SD поменять SS на 50 вот так…
const uint8_t SD_CS_PIN = 53;
И да, пины с 42 по 49 на шилде тоже можно выпаять. Они не задействованы. Ниже брошу схемку шилда.
Как я уже сказал ранее мне нужно выводить картинки с SD карты, а библиотека UTFT этого не может. Пришлось научить. Может кому понадобится…
#Вывод картинок в UTFT с SD карты.
Открываем файл UTFT.h и к прототипам функций добавляем,
void load(int x, int y, int sx, int sy, char *filename);
Сохраняем. Далее открываем файл UTFT.cpp и вставляем сразу после UTFT.h следующее. Получится вот так:
#include <SdFat.h> // тут и в скетче (для SD)
SdFile dataFile; // тут и в скетче назвать по другому например: SdFat SD;
// File Myfile; - только в скетче
Пример в скетче выше.
Ну и саму функцию вставляем где то между функциями вывода изображений
void UTFT::load(int x, int y, int sx, int sy, char *filename)
{
uint16_t result; // ширина * 2 - 1
uint8_t buf[sx*2];
cbi(P_CS, B_CS);
setXY(x, y, x+sx-1, y+sy-1);
if (dataFile.open(filename))
{
for(int n=0;n<sy;n++)
{
result=dataFile.read(&buf,sx*2);
for (int i=0; i<result; i+=2)
LCD_Write_DATA(buf[i], buf[i+1]); // выводим пиксел
}
dataFile.close();
}
else // можно убрать
for(uint16_t n = 0; n < (sx * sy); n++) // если не найден файл
LCD_Write_DATA((fch),(fcl)); // выводится пустое место
sbi(P_CS, B_CS);
clrXY();
}
И в скетче вызов функции будет таким (файл должен быть не карте, конвертор в нужный формат есть в библиотеке)
myGLCD.load(0, 0, 135, 82, "photo.raw"); //координаты(x, y), длинна, высота, имя файла
Три строки начиная с “можно убрать” можно убрать. Я добавил чтоб было наглядно видно если файл на карте не найден ну или не выводится по другим причинам, но ход до него дошёл.
Тут важный момент. Эта функция будет корректно работать только если буфер экрана заполняется с лева направо с верху в низ. Об этом чуть дальше. Немного о различиях между Mega и Due. Вывод картинка размером 128х54 с карты у Mega занимает 93 876 micros() у Due 31 314 micros(). При использовании Due, частоту тактирования карты памяти ставим 24 Мгц. Выше нет смысла. Быстрей не получается а выше 27 вообще не работает. Я думал у Due будет получатся луче, а не всего в 3 раза быстрее, но как есть и то не плохо.
Картинку выводим прямо из карты, кладя в оперативку одну строку. Считываем с карты тоже построчно. В примерах есть выводы изображений из памяти контроллера через оперативку. Мне такое не нравится. Я тем же инструментом из библиотеки конвертировал изображение в файл .h, размещал его во flash памяти и выводил прям от туда. Для сравнения такого же размера по времени Mega 43 640 micros() и Due 17 451 micros(). В два раза быстрей. Но это если они не большие и их не много. Если кому нужно и не знает как, пишите, я и так настрочил тут. С основным вроде разобрались.
Теперь немного про плюшки.
Полистав даташит стало понятно экран можно выключать, когда он не нужен и включать.
Дело в том что в библиотеке UTFT такая функция прописана и выглядит она так…
myGLCD.lcdOff();
myGLCD.lcdOn();
Но фигня в том что для нашего красавца команда не прописана. Исправляем/добавляем.
в файле UTFT.cpp ищем функцию void UTFT::lcdOn() и после break; перед фиг скобой вставляем…
case TFT01_70:
LCD_Write_COM(0x29);
break;
Для void UTFT::lcdOff() 0x29 меняем на 0х28.
Ну вот экран то мы выключили, а подсветка то осталась. В моём случаи мне нужно менять подсветку или выключать в зависимости от … Наверняка на обратной стороне все заметили резистор/перемычку один из трёх положений которого это подсветка pwm. туда его и впаиваем. А управлять уровнем будем командой. SSD1963 поддерживает 8 bit pwm с командами управления. По умолчанию он равен 240 и больше не надо. Чтоб управлять подсветкой в процессе в файл UTFT.h добавим …
void setBL(uint8_t bl);
а в Файл UTFT.cpp саму функцию…
void UTFT::setBL(uint8_t bl)
{
cbi(P_CS, B_CS);
bl = constrain(bl, 1, 245);
LCD_Write_COM(0xBE); //set PWM for B/L
/*A*/ LCD_Write_DATA(0x06); // 0b 00000110 (6)
/*B*/ LCD_Write_DATA(bl); // 0b 11110000 (240) (F0 - default) (0 ~ 255) 240 preferably
/*C*/ LCD_Write_DATA(0x01); // 0b 00000001 (1) (C[0] = 1 -> PWM ON/C[0] = 0 -> PWM OFF)
/*D*/ LCD_Write_DATA(0xF0); // 0b 11110000 (240)
/*E*/ LCD_Write_DATA(0x00); // 0b 00000000
/*F*/ LCD_Write_DATA(0x00); // 0b 00000000
sbi(P_CS, B_CS);
}
я ограничил диапазоном 1~245. Можно поуправлять через порт и наглядно посмотреть.
Вводим цифру от 0 до 255 и в порт…
if(Serial.available()){
delay(100);
uint8_t av = Serial.available(),
ser[av];
uint16_t bl = 0;
Serial.println("Serial_Avail = " + String(av));
for(uint8_t i = 0; i < av; i++){
ser[i] = Serial.read();
if(ser[i] == 10){
if(bl < 256){
Serial.println("Serial_BL = " + String(bl));
LCD.setBL(bl);
}
else
Serial.println("Serial_BL = ERROR");
Serial.println();
return;
}
bl *= 10;
bl += (ser[i] - 48);
Serial.println("Serial_Read = " + String(ser[i] - 48));
}
}
По поводу русификации я уже приводил пример. Подтянул класс Print, переписал функцию вывода символа и все плюшки Print использую полностью. В одной строке символы и цифры на нужном языке. Но такое мало кому нравиться так то это совсем другая история. А теперь, как обещал, схемка шилда. Он по сути является преобразователем уровне так как SD и SSD1963 работают на 3,3 вольт.