Графический дисплей WG12864A


04.07.2011

Наступает момент, когда для решения поставленной задачи недостаточно возможностей символьных LCD, рано или поздно приходиться переходить к графическим LCD дисплеям. Разнообразие их очень велико, и если символьные индикаторы в большинстве имеют сходный интерфейс, то интерфейс графических LCD очень сильно отличаются друг от друга. Это обусловлено использованием различных контроллеров для различных LCD от разных производителей. В этой статье расскажу о WG12864A с управляющими контроллерами ks0108 фирмы Samsung. Сам дисплей разбит на две зоны размером 64x64 за каждую зону отвечает свой чип. Выбор чипа осуществляется подачей логического уровня на выводы CS1 и CS2. При этом, есть возможность писать в оба чипа одновременно. СКАЧАТЬ ПРИМЕР использования WG12864A для WinAVR (GCC) можно здесь.  Читайте так же: Отличия WG12864A и WG12864B. Скачать обновленный пример можно здесь.

Документация и схема подключения дисплея WG12864A

Документацию по дисплею (очень скудную) можно скачать здесь.

Назначение выводов индикатора:

1.       Vss - общий 0В. 2.       Vdd - +5В питание логики. 3.       Vo - контрастность. 4.       D/I - выбор данные/инструкции 1-данные 0-инструкции. 5.       R/W - чтение/запись 1- чтение, 0-запись. 6.       E - тактирующий сигнал при записи/чтении. 7-14.  DB0-DB7 - шина данных/инструкций. 15.     CS1 - выбор кристалла. 16.     CS2 - выбор кристалла. 17.     RST - сброс. 18.     Vee - выход отрицательного напряжения. 19.     A - анод подсветки 20.     K - катод подсветки.
Схема подключения WG12864A к микроконтроллеру ATMega16/ATMega32 приведена ниже.

Немного слов о том как работает графический дисплей WG12864A. На рисунке изображен принцип адресации дисплея.

Обратите внимание, дисплей условно разделен на две части, CS1 и CS2, за которые отвечают разные чипы дисплея. Мы можем управлять одной частью дисплея, устанавливая один из сигналов CS1 или CS2. Записываемый байт изображения отображает 8 точек расположенных по вертикали. Все изображение для одного кристалла, т.е. половины дисплея, можно отрисовать матрицей шириной 64 и высотой 8 байт.

Вывод простой графики на дисплей

Все приведенные ниже примеры основаны на использовании библиотеки WG12864A.c которую можно найти в архиве с примером.


WG_init_lcd();
WG_clear();

// Example 1 BEGIN
WG_WriteXY(6,2,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0xC0,LCD_CS1);
WG_WriteData(0xE0,LCD_CS1);
WG_WriteData(0×10,LCD_CS1);
WG_WriteData(0×88,LCD_CS1);
WG_WriteData(0×88,LCD_CS1);
WG_WriteData(0×84,LCD_CS1);
WG_WriteData(0×84,LCD_CS1);
WG_WriteData(0×82,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×2,LCD_CS1);
WG_WriteData(0×4,LCD_CS1);
WG_WriteData(0×4,LCD_CS1);
WG_WriteData(0×8,LCD_CS1);
WG_WriteData(0×18,LCD_CS1);
WG_WriteData(0×30,LCD_CS1);
WG_WriteData(0xE0,LCD_CS1);
WG_WriteData(0×80,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);

WG_WriteXY(6,3,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xE3,LCD_CS1);
WG_WriteData(0xE3,LCD_CS1);
WG_WriteData(0xE3,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0xFE,LCD_CS1);
WG_WriteData(0xC0,LCD_CS1);
WG_WriteData(0×80,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0x1C,LCD_CS1);
WG_WriteData(0x1C,LCD_CS1);
WG_WriteData(0x1C,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×80,LCD_CS1);
WG_WriteData(0xFF,LCD_CS1);
WG_WriteData(0x7E,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);

WG_WriteXY(6,4,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×1,LCD_CS1);
WG_WriteData(0×7,LCD_CS1);
WG_WriteData(0xF,LCD_CS1);
WG_WriteData(0x1F,LCD_CS1);
WG_WriteData(0x1F,LCD_CS1);
WG_WriteData(0x3F,LCD_CS1);
WG_WriteData(0x3F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7F,LCD_CS1);
WG_WriteData(0x7E,LCD_CS1);
WG_WriteData(0x3C,LCD_CS1);
WG_WriteData(0x3C,LCD_CS1);
WG_WriteData(0x1C,LCD_CS1);
WG_WriteData(0x1E,LCD_CS1);
WG_WriteData(0xF,LCD_CS1);
WG_WriteData(0×7,LCD_CS1);
WG_WriteData(0×1,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
WG_WriteData(0×0,LCD_CS1);
// Example 1 END

При этом установка курсора по горизонтали от 0 до 63, а по вертикали от 0 до 8. При этом указываем, в какую часть дисплея пишем CS1 или CS2. Т.е. если нам надо что-то зарисовать с 72 точки по горизонтали, то это точка 8 (72-64), второй части дисплея. Для упрощения вывода изображения пользуйтесь функцией show_img(const char* img, uint8_t sx, uint8_t sy,  uint8_t x, uint8_t y)


const char elefant[8][74] PROGMEM =
{
{0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×80,0xC0,0×60,0×70,0×30,0×38,0×38,0×38,0×38,0x3C,0x1C,0×38,0×19,0x3F,0xFC,0×78,0×78,0xF8,0xF8,0xC0,0×80,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0},
{0xC,0x1F,0×33,0×29,0xFF,0×6,0xC,0xF8,0xC0,0×0,0×0,0×6,0xEF,0×39,0x3C,0x3E,0×36,0xE7,0xC7,0x3F,0xFF,0xF2,0xFA,0xF4,0×0,0×0,0×0,0×0,0×0,0×80,0xC3,0×43,0xC7,0xBF,0xFF,0xF8,0xA0,0xC0,0xC0,0xE0,0×60,0×60,0×60,0×70,0×70,0×60,0×60,0×60,0×40,0xC0,0×80,0×80,0×0,0×0,0×0,0×0,0×0,0xE0,0xF8,0xD8,0×18,0×18,0×38,0×78,0xF8,0×70,0×70,0×20,0×0,0×0,0×0,0×0,0×0,0×0},
{0×0,0×0,0×0,0×0,0x1F,0x7F,0xC0,0×0,0×3,0x1E,0x1C,0x1C,0x1F,0×41,0x8C,0x8E,0x8B,0xE,0×0,0×0,0×0,0×0,0×7,0x1F,0×78,0×40,0xE0,0x3C,0x3F,0×79,0×79,0x1B,0x1B,0x1B,0×13,0×73,0×67,0x2D,0xB8,0xF0,0×60,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×1,0×1,0×42,0xC6,0xCC,0×78,0x1F,0xBF,0xFC,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0},
{0×0,0×0,0×0,0×0,0×0,0×0,0×1,0×3,0×2,0xE,0xC,0xC,0xC,0×16,0×13,0×31,0×21,0×23,0×60,0×40,0xC0,0×80,0×0,0×0,0×0,0×0,0xF,0×38,0×60,0xC0,0xC0,0×80,0×80,0×80,0xC0,0×60,0x3C,0×7,0×1,0×0,0×0,0×0,0×0,0×0,0xC0,0×60,0xC0,0×70,0×90,0xE0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0xC4,0×7,0×3,0×6,0×18,0xF0,0×80,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0},
{0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×80,0×81,0xC1,0×63,0x1E,0×6,0×4,0×8,0×18,0×30,0xA8,0xB8,0xFC,0xF8,0xE0,0xC0,0×80,0×80,0×80,0×80,0×0,0×2,0xC,0xF8,0xFF,0x2E,0×27,0×3,0×1,0×0,0×0,0×0,0×0,0×0,0×80,0xE0,0xF8,0xF8,0xFF,0×98,0xC0,0xC0,0xC0,0×1,0xF,0x3C,0xE0,0xC0,0×0,0×0,0×0,0×0,0×0,0×0},
{0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0x3E,0xFE,0xFF,0xEF,0xC2,0×6,0x3C,0xF8,0xBE,0xF,0xD,0×1,0×80,0xC0,0×40,0×20,0×30,0×10,0×18,0xD,0×7,0×3,0×1,0xD,0x7F,0xC3,0×3,0×7,0xF,0x1D,0xFF,0xFE,0x3E,0x3B,0×3,0×2,0xC0,0×60,0xE0,0×10,0×18,0xC,0×6,0×3,0×3,0×1,0×1,0×1,0×3,0×6,0xC,0×18,0×18,0xB0,0xF0,0xE0,0×80,0×81,0×3,0×6,0x8C,0xF0,0xE0,0xC0},
{0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×1,0×3,0×6,0×4,0×8,0×8,0×11,0×10,0xC,0×6,0×3,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×1,0×3,0×6,0xC,0×18,0×10,0x1F,0×98,0×78,0×66,0×63,0×60,0×60,0×61,0×7,0xC,0×30,0xE0,0×40,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0xC,0x1F,0×37,0x3C,0×31,0×11,0×18,0xE,0xF,0×7,0×6,0×3,0×0},
{0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×6,0xF,0xB,0xE,0xE,0xE,0xA,0xE,0xC,0×4,0×6,0×3,0×1,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0,0×0}
};

// Example 2 BEGIN
show_img(&elefant[0][0], sizeof(elefant[0]), sizeof(elefant)/sizeof(elefant[0]), 40,0);
// Example 2 END

Эта функция выводит изображение из указанного массива в указанную позицию в пикселях. При этом массив храниться во флеш памяти и не занимает оперативную. Параметры функции void show_img(const char* img, uint8_t sx, uint8_t sy,  uint8_t x, uint8_t y) img - специально подготовленный массив sx - размер изображения по ширине sy - размер изображения по высоте x -  положение изображения на дисплее в пикселях по горизонтали y -  положение изображения на дисплее в пикселях по вертикали

Преобразование PNG файла в массив

Выписывать вручную массив точек для изображения занятие совершенно не благодарное. Чтобы избавить себя от этой рутины я написал небольшой скрипт на PHP. Скачать его можно здесь. Принцип работы прост: 1. В любом графическом редакторе рисуем черно-белое (не градации серого, а именно черно-белое) изображение размером не более 128x64 и сохраняем в формате PNG. 2. Идем по ссылке на wg12864a.php, загружаем изображение, получаем готовый код массива. Копируем, вставляем его в код программы. 3. Незабываем переименовать имя массива, если в коде используется несколько изображений.

Вывод текста

WG12864A не имеет встроенного знакогенератора, поэтому отображать буквы будем самостоятельно. Для этого нам понадобиться массив с изображением всех символов. Он находиться в файле symbols.h В этом файле описано два массива symbol - буквы, цифры и big_number - цифры большого размера.

Вывод одного символа выполняется командой WG_putc:


WG_SetTextXY(0,0);
WG_putc(‘a’,255);

Вывод строки из массива выполняется командой WG_puts:


WG_puts(0, 8, &mystring, 19, 0);

Вывод больших цифр WG_put_big_number:


WG_SetTextXY(3,5);
WG_put_big_number(9,0);

Пример:


// Example 3 BEGIN
WG_puts(0, 8, &mystring, 19, 0);
WG_SetTextXY(0,0);
WG_putc(‘a’,255);
WG_putc(‘g’,255);
WG_putc(‘a’,255);

WG_SetTextXY(3,5);
WG_put_big_number(9,0);
// Example 3 END

В функцииях вывода символов и строк есть есть параметр inv он отвечает за стиль вывода символа. Выводимый символ можно инвертировать. т.е. вывести светлым на темном. При этом используется 8 битное число, что позволяет инвертировать символ по маске, т.е. не целиком, а необходимые пиксели, например верхнюю или нижнюю часть. Пример:


WG_SetTextXY(0,0);
WG_putc(‘a’,255); // на темном фоне
WG_putc(‘g’,0); // на светлом фоне
WG_putc(‘a’,255); // на темном фоне

Вот пожалуй и все, для начала. Геометрические фигуры будем рисовать позже. Если заставить двигаться изображение по экрану, то заметим, что он немного инертен, изображение смазывается. Другими словами, для анимации он не предназначен.

Смотри так же:

7-и сегментный ЖК-индикатор. Пример использования.

Использование cимвольных жидкокристаллических LCD дисплеев. Пример на GCC (WinAVR) для Atmega 8

Отличия WG12864A и WG12864B. Скачать обновленный пример можно здесь.

Схеми і прошивки
Коментарі:
Додати коментар
Code
* - обов'язкові поля

Архіви