Графический дисплей 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. Скачать обновленный пример можно здесь.
Недавні записи
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
- DC-DC для IGBT драйверів ізольований 2 W +15 -8 вольт
- U-FOC - Векторне керування безколекторними моторами
- FOC - своя реалізація векторного керування. Підбиваю підсумки 2022 року
- Конструктор регуляторів моторів. Підбиваю підсумки 2022 року.
- Чому трифазні мотори стали такими популярними?
Tags
html uart pmsm hih-4000 mpu-9250 soldering dc-dc ethernet mpx4115a foc programmator ssd1306 bmp280 examples java-script raspberry-pi tim servo books eb-500 mongodb nodemcu docker wifi lcd adc max1674 dht11 python ssd1331 mpu-6050 remap rtc piezo solar displays led web css options dma gpio usart sms rfid esp8266 i2c 3d-printer usb pwm bldc atmega sensors barometer rs-232 git websocket motor meteo encoder bluetooth brushless timer watchdog eeprom battery st-link ngnix nvic smd stm32 flask gps capture avr bme280 flash bkp exti
Архіви