Графический дисплей WG12864A
Наступает момент, когда для решения поставленной задачи недостаточно возможностей символьных 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. Скачать обновленный пример можно здесь.
Недавні записи
- DShot receiver on STM32
- CRSF to PWM
- U-FOC PC Monitor для Chrome browser
- Фільтрація Back-EMF. Безсенсорні BLDC мотори
- Text to speech. Українська мова
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
Tags
git wifi encoder solar atmega ssd1331 sensors nvic piezo rfid smd python usb rtc motor timer bmp280 mpu-9250 barometer ethernet html books sms flask ssd1306 adc battery max1674 lcd soldering avr bldc stm32 mongodb 3d-printer remap eeprom dc-dc displays java-script nodemcu programmator gps watchdog gpio raspberry-pi websocket flash rs-232 css hih-4000 foc brushless esp8266 uart meteo bme280 mpu-6050 examples i2c servo capture bluetooth led web options bkp pwm usart exti st-link tim docker ngnix dma pmsm dht11 eb-500 mpx4115a
Архіви