В далёком 2005 году телефоны Siemens C75 и ME75 били рекорды популярности в бюджетном секторе благодаря привлекательному внешнему виду и демократичной цене.
Привлекал внимание и TFT-дисплейчик, имеющий разрешение 132x176 пикселей и палитру в 65536 цветов.
И вот, благодаря своей былой популярности, найти такие телефоны даже спустя 7-8 лет не представляет труда, и сегодня я поделюсь своими наработками, которые могут помочь использовать дисплеи данных телефонов в своих конструкциях.
Скажу сразу – данный дисплей мне очень понравился – миниатюрный, яркий и красочный, поэтому было решено продумать библиотеку для работы с ним по максимуму, т.к. при разработке своих устройств, из пары десятков индикаторов от различных старых телефонов, предпочтение отдаю именно ему.
В телефонах Siemens C75 и ME75 можно обнаружить два типа применяемых индикаторов - LPH9157-2 (с зелёным текстолитом) и некий ALPS (по крайней мере, под таким именем он фигурирует в Internet-ресурсах). Данный индикатор имеет жёлтый текстолит. В моей коллекции такой присутствует только в единичном экземпляре, поэтому написание библиотеки для работы с ним (увы!) в мои ближайшие планы пока не входит.
Дисплеи LPH9157-2 и ALPS:
Распиновка дисплея LPH9157-2:
1. CS – Chip Select. При установке в «0» контроллер дисплея принимает информацию;
2. RESET – вывод для сброса контроллера;
3. RS – вывод для определения типа передаваемых данных («0» - команда, «1» - данные);
4. SYNC – вывод для синхронизации с VGA-камерой (нам он не нужен);
5. CLK – вывод тактового сигнала для передачи данных;
6. DAT – вывод передачи данных;
7. 2,9V – к источнику питания;
8. GND – общий провод (земля);
9. VBOOST – вывод анодов светодиодов подсветки;
10. LIGHT DISP – вывод катодов светодиодов подсветки (к GND).
Схема подключения дисплея:
Резистор R7 подбирается с учётом необходимой яркости подсветки.
Для подключения дисплея к микроконтроллеру, можно собрать небольшую плату согласования уровней напряжения и оформить дисплей в виде модуля, подобно примеру в предыдущей статье. Но для желающих придать своей разработке более презентабельный вид, поделюсь печатной платой, на которой дисплей крепится в металлической рамке, снятой с платы телефона. Эту рамку, на первый взгляд крепко припаянную к основанию платы телефона, на деле легко снять с помощью скальпеля:
Оба варианта печатных плат для согласования дисплея с контроллером прилагаются в архиве.
Дисплей LPH9157-2 поддерживает три цветовые палитры: 256 цветов (8 бит на пиксель), 4096 (12 бит на пиксель) и 65536 цветов (16 бит на пиксель), в библиотеке же реализовано 2 палитры - 256 и 65536 цветов. Хотя работа с 8-ми битной палитрой предпочтительнее при небольшой частоте работы контроллера, в данном дисплее цвета в этом случае получаются очень бледными.
Datasheet на контроллер для дисплея LPH9157-2 найти не удалось, однако на глаза попался пример инициализации с подробным описанием команд, что уже было достаточно для начала экспериментов. Из команд инициализации особый интерес представляет команда Memory Access Control (36h), т.к. она позволяет задавать, с помощью следующего за ней байта данных, направление заполнения области дисплея.
В этом байте данных нас интересуют старшие 3 бита: 0bVHRXXXXX, где V – отвечает за направление заполнения по вертикали (0 - сверху-вниз, 1 - снизу-вверх), H - заполнение по горизонтали (0 - слева-направо, 1 - справа-налево), R – позволяет менять местами строки и столбцы.
Как видно из рисунка, вместе с изменением направления заполнения области дисплея, меняется и начальная позиция осей x и y.
Этого уже достаточно, чтобы при выводе текстовой информации обеспечивать программным образом поворот текста на 90º, 180º и 270º.
А почему же тогда, для правильного отображения текста, при его повороте на 90º, и 270º, не использовать возможность поменять строки и столбцы местами, чего можно добиться, устанавливая бит R в «1»?
Вот и я так подумал сначала, однако эксперимент с дисплеем показал, что фактическая область для отображения информации в этом случае ограничивается, как показано на рисунке красным цветом.
Поэтому, совместить быстрый вывод текстовой информации (предварительно задавая ту область дисплея, где предполагается изобразить символ) с возможностью изменения направления отображения текста невозможно. И, в угоду универсальности библиотеки, было решено пожертвовать скоростью вывода текстовой информации, что можно заметить при выводе большого текстового массива при малой частоте кварца микроконтроллера.
При выводе символа, функцией Send_Symbol (задаётся цвет символа и цвет фона) предварительно задаётся та область экрана, где будет отображён один байт из пяти, формирующих изображение (в библиотеке используется шрифт 5х8 пикселей). Изображение символа с помощью функции Send_Symbol_Shadow (без задаваемого цвета фона) – попиксельное.
С целью отображения на дисплее большого объёма текстовой информации, в библиотеке я использовал шрифт 5х8 пикселей, который, при увеличении масштаба изображения, немного напоминает такое течение в изобразительном искусстве, как кубизм. Вы можете использовать любой другой шрифт большего размера , для этого вам необходимо переработать функции Send_Symbol и Send_Symbol_Shadow под себя и учесть ширину символа в функциях LCD_Puts, LCD_Putsf, LCD_Puts_Shadow и LCD_Putsf_Shadow.
//=============================================================== // Функция прорисовки символа на дисплее //=============================================================== void Send_Symbol (char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot) { unsigned char temp_symbol, a, b, zw, zh, mask; if (symbol>127) symbol-=64; //Убираем отсутствующую часть таблицы ASCII for ( a = 0; a < 5; a++) //Перебираю 5 байт, составляющих символ { temp_symbol = font_5x8[symbol-32][a]; zw = 0; while(zw != zoom_width) //Вывод байта выполняется zw раз { mask=0x01; switch(rot) //Предварительно задаём область дисплея, где будет выводиться 1 байт из 5, формирующих символ { case 0: case 180: SetArea( x+zw, x+zw, y, y+(zoom_height*8)-1 ); break; case 90: case 270: SetArea( x, x+(zoom_height*8)-1, y+zw, y+zw ); break; } LCD_RS = 1; //Передаются данные for ( b = 0; b < 8; b++ ) //Цикл перебирания 8 бит байта { zh = zoom_height; //в zoom_height раз увеличится высота символа while(zh != 0) //Вывод пикселя выполняется z раз { if (temp_symbol&mask) { #ifdef _8_BIT_COLOR //(8-ми битовая цветовая палитра (256 цветов)) Send_to_lcd( DAT, t_color ); //Данные - задаём цвет пикселя #else //(16-ти битовая цветовая палитра (65536 цветов)) Send_to_lcd( DAT, (t_color >> 8) ); Send_to_lcd( DAT, t_color ); #endif } else { #ifdef _8_BIT_COLOR //(8-ми битовая цветовая палитра (256 цветов)) Send_to_lcd( DAT, b_color ); //Данные - задаём цвет пикселя #else //(16-ти битовая цветовая палитра (65536 цветов)) Send_to_lcd( DAT, (b_color >> 8) ); Send_to_lcd( DAT, b_color ); #endif } zh--; } mask<<=1; //Смещаю содержимое mask на 1 бит влево; } zw++; } switch(rot) { case 0: case 180: x=x+zoom_width; break; //Получить адрес начального пикселя по оси x для вывода очередного байта case 90: case 270: y=y+zoom_width; break; //Получить адрес начального пикселя по оси y для вывода очередного байта } } } //=============================================================== // Функция вывода одного символа ASCII-кода (из файла Symbols.h) //=============================================================== void LCD_Putchar(char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot) { unsigned char m; if(zoom_width == 0) zoom_width = 1; if(zoom_height == 0) zoom_height = 1; switch (rot) { case 0: //Начальный адрес осей Х и У - левый верхний угол дисплея Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot); break; //================================ case 90: m=y; y=x; x=m; Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x40); //Начальный адрес осей Х и У - правый верхний угол дисплея Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot); Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x00); break; //================================ case 180: Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0xC0); //Начальный адрес осей Х и У - правый нижний угол дисплея Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot); Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x00); break; //================================ case 270: m=y; y=x; x=m; Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x80); //Начальный адрес осей Х и У - левый нижний угол дисплея Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot); Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x00); break; //================================ default: Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x00); //Начальный адрес осей Х и У - левый верхний угол дисплея Send_Symbol( symbol, x, y, t_color, b_color, zoom_width, zoom_height, rot); Send_to_lcd(CMD, 0x36); Send_to_lcd(DAT, 0x00); //================================ }; }
Также, при использовании библиотеки, следует иметь ввиду, что при запуске дисплея, начало адреса осей X и Y – левый верхний угол, а при изменении направления вывода текста или изображения (90º, 180º, 270º), осью X всегда будет считаться сторона над верхней частью выводимого текста или изображения.
Библиотека (для CodeVisionAVR) работы с LPH9157-2 содержит следующие функции (приведены только пользовательские функции!):
1. void LCD_init ()
Инициализация дисплея.
2. void Put_Pixel (char x, char y, unsigned int color)
Функция вывода точки (пикселя). x и y – координаты экрана, где будет отображён пиксель цветом color.
3. void LCD_Putchar (char symbol, char x, char y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода одного символа ASCII-кода. Данная функция рассчитана на вывод символов размером 5х8 пикселей, библиотека которых находится в файле Symbols.h. symbol – выводимый на экран символ в ASCII-кодировке; x и y – начальная координата вывода символа; t_color – цвет пикселя; b_color – цвет фона; переменные zoom_width и zoom_height увеличивают символ на экране в указанное число раз; rot – угол поворота текста (0º , 90º, 180º, 270º).
4. void LCD_Putchar_Shadow (char symbol, char x, char y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 3, только без цвета фона.
5. void LCD_Puts(char *str, int x, int y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода строки, расположенной в ram-памяти микроконтроллера. В отличие от библиотеки для LPH8731-3C, для вывода строки задаётся не номер строки и столбца, на которые предполагаемо разбит экран, а адреса начальных пикселей x и y.
6. void LCD_Puts_Shadow (char *str, int x, int y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 5, только без цвета фона.
7. void LCD_Putsf(flash char *str, int x, int y, int t_color, int b_color, char zoom_width, char zoom_height, int rot)
Функция вывода строки, расположенной во flash-памяти микроконтроллера.
8. void LCD_Putsf_Shadow (flash char *str, int x, int y, int t_color, char zoom_width, char zoom_height, int rot)
То же, что и 7, только без цвета фона.
9. void LCD_FillScreen (unsigned int color)
Функция заливки экрана цветом color.
10. void LCD_Output_image (char x, char y, char width, char height, flash char *img, int rot)
Функция вывода картинки. x и y начальная позиция выводимого на экран изображения; width и height – ширина и высота изображения (в пикселях); *img – указатель на массив данных, составляющих изображение; rot – угол поворота изображения (0º , 90º, 180º, 270º). Данная функция предполагает, что массив данных изображения расположен во flash-памяти микроконтроллера. Для преобразования необходимого вам изображения в массив, содержащий цвет пикселей, можно воспользоваться программами Image2Lcd или Nokia Image Creator, которые несложно найти на просторах интернета. Единственное требование – направление вывода массива изображения должно выполняться слева-направо, сверху-вниз! При использовании 16-ти битной палитры, при преобразовании изображения в массив типа char, обязательно старший байт должен идти первым!
11. void LCD_DrawLine (char x1, char y1, char x2, char y2, int color)
Нарисовать линию. x1 и y1 – начальная позиция линии; x2 и y2 – конечная позиция линии.
12. void LCD_DrawRect (char x1, char y1, char width, char height, char size, int color)
Нарисовать рамку. size - толщина рамки.
13. void LCD_FillRect (char x1, char y1, char width, char height, int color);
Нарисовать прямоугольник.
14. void LCD_DrawCircle (char xcenter, char ycenter, char rad, int color);
Нарисовать окружность. rad – радиус окружности в пикселях.
15. void LCD_FillCircle (char xcenter, char ycenter, char rad, int color);
Нарисовать круг, заполненный цветом color.
16. void LCD_DrawTriangle (char x1, char y1, char x2, char y2, char x3, char y3, int color)
Нарисовать контуры треугольника.
17. void LCD_FillTriangle (char x1, char y1, char x2, char y2, char x3, char y3, int color)
Нарисовать треугольник, заполненный цветом color.
В самом начале библиотеки, если объявлен макрос _8_BIT_COLOR, то цветовая палитра дисплея будет составлять 256 цветов, иначе - 65536 цветов. Макрос _GEOMETRICAL позволяет использовать функции вывода линии, рамки, прямоугольника, окружности, круга и треугольника.
- LPH9157-2.rar (7 Кб)
- LPH91572-Платы под ЛУТ.rar (40 Кб)
Комментарии (33) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
[Автор]
//==================================
// Аппаратный SPI
//==================================
void Send_spi(unsigned char data)
{
//Частота сигнала SCK: Fкварца/16
SPCR = (1 сдвиг влево SPE)|(1 сдвиг влево MSTR)|(1 сдвиг влево SPR0);
SPDR = data;
while(!(SPSR & (1 сдвиг влево SPIF)));
SPCR = 0;
}
#endif // _USE_SOFT_SPI
[Автор]
[Автор]
Правильно я понимаю что вместо дрыганья clk, нужно просто дрыгать точно также write, а байт данных сразу выставить в какой нибудь порт?
(Ну вот никто не хочет делится)
https://github.com/skadiexe/LPH9157-2-display-arduino-library
https://github.com/Azq2/stm32-lcd-lph8924-1
Низкоуровневая либа.