Работа с графическим дисплеем WG12864 на базе контроллера KS0107

Обычно для вывода информации сигнального дисплея на HD44780 более чем достаточно. Но иногда нужно нарисовать картинку, график или хочется сделать красиво, с модными менюшками. Тут на помощь приходят графические дисплеи. Одним из самых простых и доступных является дисплей на контроллере KS0107 или аналоге. Например, WG12864A от Winstar. Сам дисплей вполне свободно достается, имеет довольно большой размер (диагональ около 80мм) и разрешение 128х64 пикселя. Монохромный. Цена вопроса 400-500р.
 

Вот такой вот:


Подключение
Управление дисплеем параллельное. Есть шина данных и линии задания направления и вида данных. Это, кстати, один из минусов — требует очень много проводов управления. Занимает почти 16 линий. Но зато и очень прост в работе.
 

Итак, если взять тот, что у меня WG12864A-TGH-VNW то у него следующая распиновка:

 

  • Vdd и Vss это питание, оно у него пятивольтовое.
  • Vee — источник отрицательного напряжения. Там примерно минус 5 вольт. Есть не на всех моделях этих дисплеев, у Winstar о наличии такой фенечки говорит буква V в маркировке. WG12864A-TGH-VNW
  • Vo — напряжение регулировки контраста. Туда подается либо 0…5 вольт, либо от -5 до 5, в зависимости от модели и температурного диапазона. Обычно более морозостойкие дисплеи требуют отрицательное напряжение. Схема включения простая:
  • D/I — Данные/команда. Логический уровень на этом выводе определяет предназначение кода на шине данных. 1 — данные, 0 — команда.
  • R/W — Чтение/Запись. Уровень на этой ноге задает тип действия. 1 чтение, 0 запись.
  • Е — Строб, синхронизирующий импульс. Дрыг этой вожжи вверх-вниз проворачивает шестеренки в интерфейсе контроллера.
  • DB0..7 — Шина данных, на которую мы выдаем нужный нам код.
  • CS1 и CS2 — выбор контроллера.
  • RST — сигнал сброса. Ноль на этой линии сбрасывает контроллеры в ноль. Но не сбрасывает видеопамять, только текущую адресацию.
  • A и K — питание светодиодной подсветки. Там, как правило, обычные светодиоды, так что напрямую туда 5 вольт подавать нельзя. Только через ограничительный резистор. Ток потребления подсветки весьма велик, около 200мА, падение напряжения в районе 4 вольт. На пяти вольтовом питании ограничетельный резистор должен быть порядка 5-10 Ом.

 
К контроллеру (ATMega16 на Pinboard) я подключил все следующим образом.


 

Данные полностью легли на PORTA, а управление на PORTB. В качестве резистора подстройки контраста я взял многооборотный переменник, что так кстати стоит рядом для подобных случаев. Питание подсветки взял с колодки от дисплеяя. Благо там все уже готово, даже управление от транзистора есть :) Правда я ее просто включил.
 

 

Двое из ларца, одинаковых с лица. Адресация
Контроллер CS0107 он может организовать матрицу только 64х64. А у нас в дисплее вдвое большая 128х64. Значит стоят два контроллера. Один отвечает за правую половину экрана, другой за левую.
Он представляет собой этакую микросхему памяти, где все введенные данные отображаются на дисплее. Каждый бит это точка. Кстати, для отладки удобно юзать, выгружая туда разные данные, а потом разглядывая этот дамп). Карта дисплея выглядит так:
 

 

Байты укладываются в два контроллера страницами по 64 байта. Всего 8 страниц на контроллер.
 

Так что для того, чтобы выставить точку с координатами на экране, например, Х = 10, Y=61 надо вычислить в каком контроллере она находится. Первый до 63, второй после, если адрес во втором контроллере, то надо вычесть 64 из координаты. Затем вычислить страницу и номер бита. Страница это Х/8, а номер бита остаток от деления (Х%8). Потом нам надо считать нужный байт из этой страницы (если мы не хотим затронуть остальные точки), выставить в нем наш бит и вернуть байт на место.
 

 

Протокол обмена
Тут все просто, без каких либо изысков. Выставляем на линиях RW, DI что мы хотим сделать, линиями CS1 и CS2 выставляем к кому обращаемся. На шину данных выдаем нужное число и поднимаем-опускаем линию строба. Опа! Впрочем, есть одна тонкость. Для чтения данных строб нужно дернуть дважды, т.к. предварительно данные должны попасть в регистр-защелку. Для чтения же флага состояния такой изврат не нужен. Вот примеры временных диаграм для разных режимов.
 

Чтение

 

И запись. Причем запись, в отличии от чтения, можно делать сразу в оба контроллера. Конечно одновременно писать данные в контроллер смысла имеет мало, разве что захочишь двойную картику получить :) А вот команды обычно пишут срзау в оба.
 

 

Кстати, еще есть одна особенность — выводы CS могут быть инверсными. Это зависит от модели дисплея. Так что это надо учитывать.

 

Временные диаграммы, т.е. сдвиг фронтов между собой по времени может быть разным у разных контроллеров. Где то быстрей, где то медленней. Но в целом 1мкс обычно хватает. В реале обычно меньше. Лучше поглядеть в даташите на конкретный контроллер (не дисплей, в ДШ на дисплей обычно редко есть описание самого контроллера). Там обычно есть таблица вида:

Где указаны максимально допустимые временные интервалы. Если они будут меньше или больше, то дисплей скорей всего не будет работать. Или будет работать с ошибками. Если у вас на дисплей в процедуре заливки или очистки экрана полезли всякие левые пиксели и прочие артефакты — значит тайминги не выполняются. Также рекомендую проверять тайминги на чтение и на запись. Делается это просто — гоним последовательно сначала чтение, а потом запись обратно. Если ничего не изменилось — значит все ок. Появились искажения? Крутите временные задержки. Только рекомендую читать не пустоту вида 0х00, а что нибудь более веселое залить, например, шахматную доску из пикселей. По очереди 0х55 и 0хАА.
 


 

Система команд.
Она тут простейшая.

Команда D/I R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 Назначение
Отображение ВКЛ/ВЫКЛ L L L L H H H H H L/H Управляет вкл/выкл отображения. Не влияет на внутреннее состояние и данные ОЗУ изображения.
L: ВЫКЛ
H: ВКЛ
Установить Адрес L L L H Адрес Y (0 ~ 63) Заносит адрес Y в счётчик адреса Y
Установить Страницу (адрес Х) L L H L H H H Страница (0 ~ 7) Заносит адрес X в регистр адреса X
Начальная Строка Отображения L L H H Начальная строка отображения (0 ~ 63) Скроллинг вверх. На сколько пикселей сдвинуть адресное пространство. При этом уехавшее вверх, за экран, вылезет снизу, словно мы провернули экранную область как барабан
Чтение Состояния L H BUSY L ON/OFF RESET L L L L Чтение состояния.
BUSY
L: Готовность
H: Выполняется команда ON/OFF
L: Отображение ВКЛ
H: Отображение ВЫКЛ
RESET
L: Нормальный режим
H: Сброс
Запись Данных Изображения H L Данные для записи Записывает данные (DB0:7) в ОЗУ данных изображения. После записи инструкции, адрес Y увеличивается на 1 автоматически.
Чтение Данных Изображения H H Данные для чтения Читает данные (DB0:7) из ОЗУ данных изображения на шину данных. После чтения адрес Y сам увеличивается на 1 автоматически

 

Инициализация дисплея элементарная, в отличии от HD44780, где надо переключать режимы, включать-выключать разные курсоры и отображения.
 

Надо после сброса задать начальные координаты (адрес точки и страница), значение скролинга (обычно 0) и включить отображение. При включении на дисплее может быть мусор. Поэтому отображение обычно включают после очистки видеопамяти.
 

У меня ициализация, по командам, выглядит так:
 

  • 0x3F — включить
  • 0x40 — Адрес Y=0
  • 0xB8 — Страница Х=0
  • 0xC0 — Скролл = 0 (т.е. с самого верха)

 

Ну и потом еще заливка сразу в оба контроллера.
 

Код
Итак, приступим к коду. Чтобы было наглядней я все операции с ногами расписал в виде макросов. Заодно будет гораздо проще все перенести на другую архитектуру. Просто написав другие макросы, не правя сам код :)
Весь код можно поглядеть в нашей кодосвалке:
lcd_wg128.h
lcd_wg128.c
 

Покажу тут лишь характерные моменты работы с дисплеем.
 

Записью команд и данных занимаются следующие функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Пишем команду в выбранный контроллер
void LCD_WR_COM(u08 cmd,u08 CSC)
{			// Поднятие сигналов:
LCD_SET_CMD;		// Команда
LCD_SET_W;		// Запись
 
ON_CS(CSC);		// Выбор чипа
 
LCD_DATA_INS(cmd);	// Команду на шину данных
 
NOPS;			// Подождем
LCD_PUL_E;		// Дрыгнем стробом
NOPS;			// Подождем
 
LCD_OFF_CS1;		// Выключим 
LCD_OFF_CS2;		// выбор кристалла
}
 
// Пишем данные в контроллер
void LCD_WR_DATA(u08 cmd, u08 CSC)
{			// Поднятие сигналов
LCD_SET_DAT;		// Данные
LCD_SET_W;		// Запись
 
ON_CS(CSC);		// Выбор чипа
 
LCD_DATA_INS(cmd);	// Данные на шину данных
 
NOPS;			// Подождем 
LCD_PUL_E;		// Дрыгнем стробом
NOPS;			// Подождем
 
LCD_OFF_CS1;		// Выключим выбор
LCD_OFF_CS2;		// Чипа.
}
 
// Чтение данных из байта, адрес которого уже должен быть установлен. Надо только выбрать
// контроллер.
u08 LCD_RD_DATA(u08 CSC)
{
u08 outv;
			// Выставляем линии управления
LCD_SET_DAT;		// Данные
LCD_SET_R;		// Чтение
 
ON_CS(CSC);		// Выбираем чип (только один!) 
 
NOPS;			// Ждем
LCD_PUL_E;		// Дрыг стробом - пустое чтение, активация защелки
NOPS;			// Ждем
 
LCD_UP_E;		// Строб вверх
NOPS;			// Ждем
outv = LCD_DATA_PIN;	// Контроллер выдал данные на шину. Читаем их 
LCD_DN_E;		// Строб вниз
 
LCD_OFF_CS1;		// Все свободны!
LCD_OFF_CS2;
 
return outv;		// Возвращаем считанное 
}

 

Чтение слова состояния делать не стал. Т.к. дисплей работает весьма шустро, что на круг ожидания можно не уходить, а просто подождать несколько тактов. Собственно этих трех функций уже достаточно для работы :) Остальное все свистоперделки и удобства.
 

Вроде заливки экрана:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Заливка экрана 
void LCD_FILL(u08 byte)
{
	for(u08 i=0; i<8; i++)			//Перебирая страницы X от 0 до 7
	{
	LCD_WR_COM(0xB8+i,(1<<CS1|1<<CS2));	//Льем параллельно в оба чипа. 0xB8 задает тип операции (адрес страницы)
 
	for(u08 j=0; j<64; j++)			// Задаем адрес Y от 0 до 64
		{
		LCD_WR_COM(0x40+j,(1<<CS1|1<<CS2));		// Записываем адрес У в контроллер.
		LCD_WR_DATA(byte,(1<<CS1|1<<CS2));		// Записываем в байт с адресом ХУ  нужное значение
		}
	}
}

 

Или установки пикселя. Причем можно загонять его в трех режимах. Просто установить, стереть или инвертировать. Координаты задаются глобальные, а вычисление адреса идет в функции:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Процедура установки пикселя. Т.к. пиксель часть байта, то надо сначала вычислить
// Контроллер, потом страницу и нужный байт. Считать этот байт. Изменить в нем только один,
// нужный, бит и вернуть его на место.
// На входе координаты и режим обработки пикселя (вкл, выкл, переключение)
void PIXEL(u08 x,u08 y,u08 mode)
{
u08 CSS, row, col, byte;
u08 res,read;
 
if(y>63)			// Проверяем в каком контроллере искомый пиксель
	{
	CSS = 1<<CS2;		// Если У больше 63 значит во втором. Выставляем 2й 
	col = y-64;		// И отнимаем смещение, чтобы не мешалось. 
	}
else
	{
	CSS = 1<<CS1;		// Иначе контроллер у нас первый. 
	col = y;			// А смещения нет. 
	}
 
row = x>>3;			// Делим Х на 8, чтобы получить номер страницы. 
byte = 1<<x%8;			// А остаток от деления даст нам искомый бит, который мы задвигаем
				// и получаем нужную нам битмаску для модификации байта. 
 
SET_ADDR(row,col,CSS);		// выставляем адрес
read = LCD_RD_DATA(CSS);	// Читаем данные (адрес при этом ++ аппаратно). 
 
switch(mode)			// В зависимости от режима
	{
	case 0:			// Clear
			{
			res = read & ~byte;	// Накладываем сбрасывающую (NOT) маску
			break;
			}	
	case 1:		// Invert
			{
			res = read ^ byte;	// Накладываем инвертирующую (ХОR) маску 
			break;
			}
	default:		// Set
			{
			res = read | byte;	// Накладываем устанавливающую (OR) маску
			break;
			}
	}
SET_ADDR(row,col,CSS);		// Повторно выставляем адрес. Т.к. чтение его исказило.
LCD_WR_DATA(res,CSS);		// Вгоняем туда результат нашей модификации. 
}

 
Но работа с пикселями медленная штука. Это же каждый надо считать, изменить, закинуть обратно. Куча мороки. На обновление всего экрана в попиксельном режиме уйдет прорва времени. Я подсчитывал, при полной загрузке проца только на это, на заливку попиксельно всего экрана уходит чуть ли не треть секунды.
 

Куда эффективней работать с дисплеем блоками. Т.е. берем и последовательно записываем сразу куски страниц, на глубину в несколько байт. Например, таким образом удобно рисовать текст. Правда при попиксельном выводе, когда текст попадает между страницами получается неудобно, приходится делать вдвое больше работы. Но все равно намного быстрей чем попиксельно. На порядок!
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Запись сразу блока. Удобно для вывода строк или картинок, постранично. 
// На входе страница Х и колонка У. А также длина блока и адрес откуда брать данные.
u08 BLOCK(u08 x,u08 y, u08 len, u16 addr)
{
u08 CSS,i,col;
 
if(y>63)			// Сначала вычисляем нужные нам сегмент (чип)
	{
	CSS = 1<<CS2;
	col = y-64;
	}
else
	{
	CSS = 1<<CS1;
	col = y;
	}
 
SET_ADDR(x,col,CSS);		// Ставим адрес
 
// А дальше в цикле гоним байты. Не забывая увеличивать адрес, чтобы была выборка из
// памяти. Счетчик, чтобы не сбиться со счета. И номер колонки, чтобы не вылезти за границы
// И вообще понимать где мы находимся. 
for(i=0;i!=len;i++,addr++,col++)
	{
	if(64==col)			// Попутно проверяем за границы выхода из сегмента
		{
		if(CSS == (1<<CS2))	// Если случилось, и у нас второй сегмент, т.е. конец
			{		// страницы (уже второй в этой строке)
			return 128;	// выходим с кодом ошибки (код больше разрешения экрана)
			}
 
		col=0;			// Иначе же обнуляем счетчик колонок. И переключаем банку
		CSS = 1<<CS2;		// Выбрав второй сегмент экрана
		SET_ADDR(x,col,CSS);	// И выставив новый текущий адрес
		}
 
	LCD_WR_DATA(pgm_read_byte(addr),CSS);	// Пишем туда данные прям из флеша (таблица символов). 
	}
return y+len;				// Возвращаем координату увеличиную на размер блока.
}

 

Блочный вывод легко превращается в текстовый вывод. Надо лишь совместить таблицу символов с печаталкой блоков. И гнать данные из флеша напрямую.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Процедура вывода строки. На входе строка, и координаты. Х в страницах, а У в точках.
void LCD_putc(u08 x,u08 y,u08 *string)
{
u08 sym;
 
while (*string!='\0')		// Пока первый байт строки не 0 (конец ASCIIZ строки)
	{
	if(127<y)		// Проверяем за границу выхода за экран. Если вылезаем
		{		// Вот тут, кстати, можно поиграть с числом, чтобы не рубило последний символ.
		y=0;		// То обнуляем координату точки. 
		x++;		// Выставляем следующую строку
		if(x>7) break;	// Если экран и вниз кончился - выход. 
		}
 
	sym = *string-0x20;	// Вычисляем из ASCII кода смещение в таблице символов. 
				// Для русского языка и цифр надо условия добавить. Т.к. 
				// таблица там не полная, не 255 байт.
 
	y = BLOCK(x,y+1,5,(u16)symboltable+sym*5);		// Закатываем этот блок. 
	string++;						// Не забывая увеличивать указатель,
	}
}

 

Для еще большего ускорения можно немного оптимизировать функции ввода вывода. Убрав из хвостов возврат сигналов в первоначальное положение. У меня они больше для красоты. Да чтобы на экране анализатора было лучше видно :)
 

Ну и чтение-модификацию-запись делать тоже большими блоками. Загоняя, скажем, страницу в буфер, правя его там и быстро выгружая обратно.
 

Ну и, традиционно, архив с примером. Сделано все на ATmega16 под WinAVR GCC на Pinboard
 

110 thoughts on “Работа с графическим дисплеем WG12864 на базе контроллера KS0107”

  1. Зачетно
    Надо бы свой прикрутить, попробовать, а то валяется на полке.
    Цены на них откровенно безбожные, учитывая, что TFT 2.4″ у китайцев стоят 20$.
    Кстати, удобно еще генерить массив какой-нибудь прогой, потом просто выводить на экран. Я с tic-ами там делал. Для статичной фигни.

    1. TFT так просто не обработаешь, под него нужен мощный контроллер, а лучше ПЛИС и видеопамять. Так что не все так просто.

      Можно да, но его надо гдето в памяти держать. Тут получается килобайт только фреймбуфер.

      1. Контроллер обычно в таком дисплее есть.
        Видеопамяти все равно не напасешься, особенно с двойным буфером.
        К примеру, для 7″ (800х480) дисплея с глубиной цвета 24 бит, нужен мегабайт с лишним памяти. RAMа больше 128К я вроде не видел в МК.
        Но в целом да, ресурсы все равно нужны свободные.

      2. Мощный то и не нужен, lpc2478 или lh79520 отлично справятся, только если хранить картинки нужно, то лучше прикрутить внешний nand мега на 4

      1. А последняя работа была какая?
        Ди. Раз ты тут. Скажи своей жене чтобы она занялась моим заказом :) 701 вроде.

        1. Последний раз я был наладчиком лабораторного оборудования. До этого наладчиком станков ЧПУ, а до этого я был студентом :)

          Я его уже обработал. Гляди в форум :)

  2. А есть ещё такие же по габаритам на контроллере ST7920. Брал у братьев китайцев. Так они ещё и последовательный интерфейс умеют ;-)

      1. Вопрос снят — у своеобразная адресация GDRAM.

        Верхняя половина экрана.
        y=0 … 31
        x=0 … 7

        Нижняя половина экрана.
        y=0 … 31
        x=8 … 15

        Посылать два байта данных (2*8 * 8 = 128 точек).

  3. Есть клёвые экранчики от Noka 1110i/1112, по ~50р в каком-нибудь сириусе, рублей за 30 у кетайцев. Протокол контроллера на базе SPI давно уже раскурочен, разрешение 128×160, размеры не очень большие, чёрно-белый.

    Да и вообще — экраны от телефонов — самые дешёвые, функциональные и есть огромный выбор. Огромное количество протоколов описано тут: http://www.module.ro/, рекомендую.

    1. Ага и до них скоро доберусь. Проблема этих дисплейчиков в том, что их сложно покупать оптом.

          1. Да, растаможка это зло. Можно по 10 штук заказать себе, соседу, маме и другу :). Хотя один раз удалось убедить таможню, что сотня аккумуляторов на 5.5 А*ч нужны для личного потребления :)

            А можно растаможку оставить на совести Сириуса: http://shop.siriust.ru/product_info.php/products_id/9711
            :)
            Даже если у них нет столько в наличии, думаю, под заказ сделают, они один фиг регулярно растамаживают кучу всего.

    2. У китайцев вообще много всего интересного. Вот по $9 например шикарнейшие цветные 3″ TFT 256×192 от NintendoDS http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=230457012096&ssPageName=STRK:MEWNX:IT#ht_2157wt_1396
      правда выводов туча (распайка с сигналами есть).
      Или вот от Самсунга http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=300575859205&ssPageName=STRK:MEWNX:IT#ht_1255wt_1163 на контроллере HD66773R — тоже вариант IMHO.
      Но avr’ки гонять на этом конечно не айс.

      P.S. Вот и получается — что 8-битный AVR+текстровый/граф.ЧБ экран средней фиговости — в сумме ДОРОЖЕ чем 32-битный Cortex M3+навороченный цветной TFT 3″ :)

      1. Ммм я китайцев вообще не рассматриваю. Один два дисплея купишь, а вот сотни три в квартал уже гемор.
        Думаю тот же WG12864 в китае тоже стоит копейки. Кстати, а счего это на кортексе хорошая графика взлетает?

        Памяти у него не сильно то больше, на цветной точно не хватит полноценный фреймбуфер сделать. Ногами дрыгать он умеет плохо. А с внешней видеопамятью + контроллер на ПЛИС который будет ее вгонять в дисплей это уже совсем другая история. Или там спец кортексы, с интерфейсом дисплея и видеопамятью замапленной в адресное пространство?

        1. Про оптовые поставки из китая — это всё далется. Списываются с поставщиком (который на том же eBay и прочих), договариваются о форме взаимодействия, оформляют доки, проводят через таможно и т.п. Можно юзать как посредников российские конторы, у которых налажена связь с Китаем.

          Про кортекс — ага, с внешней SRAM (+ещё 2 копейки), высокая тактовая частота и конечно DMA рулят — можно вполне приличное разрешение использовать. ПЛИС не нужен.

          1. В догонку из AN3241 от ST:
            The STM32 with its powerful DMA controller and highly flexible FSMC peripheral combine to offer a cost-effective solution for driving a QVGA TFT-LCD with a CPU load of only 1% for static image display.

        2. У STM32 FSMC вполне справляется, по-крайней мере с 2.4″ TFT.
          Тут скорее зависит от памяти граф. контроллера.
          У меня есть плата с Pic32 и граф. контроллером SSD1963, у пика «всего» 32К RAM памяти, в контроллере мег с небольшим. Дисплей 7″ нормально отображает движущиеся объекты, разве что мерцание немного видно под углом.
          Видимо буфер передается частями, я пока не разобрался в этой части кода (там microchip GUI немного обработанный и с драйвером под 1963).

          1. Ну в принципе, SPI на предельной скорости, да через DMA вполне может дать вменяемое быстродействие. Просто сложно всякие эффекты рисовать, придется их по частям прорисовывать если на лету. Или с флешки какой грузить.

        3. STM32F103, AFAIK не имеющий встроенного контроллера, в одиночку справляется со всеми задачами в DSO Nano, включая вывод на дисплей с TFT интерфейсом. Так что, видимо, все не так уж плохо.

      1. Пардоньте, обшибся.
        Просто побывавши на module.ro, глаза разбегаются а мозг затуманивается от обилия перспектив :)

  4. На самом деле такие дисплеи среди любителей не так распространены, как дисплейчики от телефонов. ИМХО.

    Упячкомен доставил :)

  5. Именно этот дисплей к интерфейсу внешней памяти не прикрутить. Как раз в статье Steel_ne’ла, об этом и написано — E — сигнал мешается.

    Для ускорения вывода можно использовать кеш. Т.е. хранить несколько байт в памяти. все операции с установкой пикселя проводить в памяти, и как только последующий пиксель окажется за пределами кэшируемой области — сливать кешь в дисплей, и загружать новые данные с дисплея и опять то же самое.
    Быстро получается выводить текст, когда шрифт организован так, как пиксели расположенны в дисплее по байтам, например, в этом дисплее один байт — это вертикальная линиия, значит шрифт надо выводить по вертикальным линиям. Тогда, организовав кэшь размером с ширину одного символа, можно быстро текст печатать. Единственно, после вывода последнего символа надо флашь кэша делать.

  6. Помоему проще сделать контроллер вывода для такого дисплея на отдельном контроллере, и слать ему просто текстовые команды, уже были статьи по «самодельным» контроллерам ввода-вывода. Основной задачей занят один контроллер, опросом кнопок и дисплеем другой, помоему удобно и ускоряет разработку.

      1. Да полюбому, даже на компе многоядерном, и многогигагерцовом картинки рисуют вспомогательные контроллеры.

        1. в принципе… туда можно запихать виртуальную машину со своим языком и получить сопроцессор графики. На вход скрипты (типо линия с координатами от сих до сих) на выходе линия на дисплее и прерывание «ОК»

          1. Если кому интересно, то такой виртуальной машиной для графики является PostScript и его развитие в виде Adobe PDF, а в основе всего стоит FORTH машина…

    1. Есть такая прикольная штука от Atmel как DB101 с дисплеем 128х64 на контроллере s6b1713.
      http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4221
      http://gandalf.arubi.uni-kl.de/avr_projects/db101_gcc_20080301.zip
      К этой штуке идет полный набор графических библиотек с виджетами, кнопками, прокрутками,
      окнами….. Вот бы, к этой библиотеке, WG12864 на базе контроллера KS0107 да прикрутить !

  7. А дисплей WH1602A от WinStar (16×2) также подключать? Или как в статье «Подключение к AVR LCD дисплея HD44780»?

  8. Для дисплеев WG12864 в пакете MikroC есть тулза, которая позволят монохромные битмапы загонять в программу в текстовом виде. Удобно.

  9. Ди, можно схему включения немного покрупнее?
    или еще одну картинку покрупнее по ссылке «увеличить»

  10. DI HALT. Не против испробовать такой дисплей WG12864F c контролером T6963. занятная штука имеет на борту 8кб при маленьком изменении можно сделать 32кб отдельно символьные страницы отдельно графические страницы но выводит на экран обе части. возможность переключения между страницами, скорость передачи, приема намного выше чем на KS0107.

    1. Совершенно не против. Только нет у меня его в наличии :) А заказ я уже сделал и следующий только через несколько месяцев.

      1. ну ничего, я к тому что весчь оч. интересная. если что, есть некие наработки, но это только для серьезных конструкций.

  11. Спасибо за статью. Вдохновился и заказал с e-bay экран 128х64. Но он на контроллере ST7920. Внутри и символьный, и граф. экран.
    Управляющую программу начал на Си. Обычно на асм писал.
    В симуляторе AVR studio 4 всё работает, как надо.
    В реале на порт B выдаются правильные данные. На порт A 3 бита управления (RS — статический 0, RW статический 1, E — правильный пульс)
    Может кто подскажет в чём дело?
    Код не такой длинный…
    http://easyelectronics.ru/repository.php?act=view&id=59

    1. У тебя между выводом cmd1 и cmd2 нет никакой выдержки. Может контроллер просто не успевает один байт прожевать, а ты ему уже второй пихаешь?

      1. выдержку поставлю… не понимаю почему RS (PortA,0) выдаёт статический ноль…
        кстати, на порте C точно такой же код и ситуация иная… RS работает, а E (PortC,2) статический ноль…

        1. А какой контроллер? Может забыл запитать портА?

          Плюс на Атмега16,32 по дефолту включен жтаг и порт С наполовину не работает, т.к. на нем висит жтаг. Его надо выключить программно или фузбитом.

          1. так ATmega32 и есть… может быть в этом и кобыла зарыта…
            а про порт А не понял… там же ADC входы, просто сконфигурировал их на выход.

                  1. DI, спасибо за ответы! Экран заработал через порт С после отмены JTAG. (Грабли, конечно, в следующий раз буду смотреть).

  12. Di? привет, скажи, примеры кода в чем написаны?
    я понимаю что под Атмегу, но я хочу на PIC и уверен что есть под него аналогичная среда программирования.

  13. Di привет. А ведь заметил я, что ты чаще стал писать примеры для статей на си. Видать ассемблер тебя слегка уже подзаколупал.

    1. Просто я попутно готовлю почву перехода на STM32 и ARM и потому писать на асме это путь в один конец. А на Си код переносится махом. Обрати внимание как он написан, железоориентированного кода в самом коде минимум. Разве что в дефайнах всяких. Потом просто эти примеры под STM32 портирую и все.

      А так, свои проекты пишу и на том и на другом. В зависимости от масштаба задачи.

  14. Не в тему, но близко: кто знает, существует ли таблица с обзором и сравнением символьных ЖК типа WH-ххyy от различных производителей? Чем отличаются, какие фичи, питания, доп. интерфесы, етс.

    Развелось куча подобных (типа FECCxxyy,DV-xxxxx, др.),
    цены на 1602 видел аж 83р в розницу ..

  15. Если посмотреть на тайминги в даташите, то время исчисляется десятками наносекунд. При тактовой частоте проца 8мгц, за миллисекунду выполняется порядка 8 одно тактовых инструкций. То есть, процессор очень тормозной для LCD дисплея (почти в 1000 раз) и поэтому задержки в командах чтения записи можно полностью убрать.
    Я проверял на дисплеях MTG-S12864B WM-G1206M все работает.

  16. Собрал схемку на меге8, подключил дисплей, у меня HG12605ny, на нём всё тот же ks0107b и 08. В протеусе всё работает, но вот в готовом устройстве дисплей не проявляет никаких признаков жизни. Можно как-то проверить работоспособность в принципе? может демка или чтоб всё вместе засветилось или даже пусть всё болото из памяти какое есть. Посоветуйте.

    1. Важно наличие отрицательного напряжения на выводе Vo. Некоторые урезанные дисплеи не имеют на борту инвертора, выдающего отрицательное напряжение на вывод Vee.

    2. Всем привет!
      Не так давно стал изучать программирование AVR на С c Atmega16
      Появился индикатор FDCG12864B хотел бы его подключить вывести графику и текст.
      Возник вопрос:
      1. линии CS1 и CS2 у моего дисплея инвертные это как?
      2. есть у кого программа на С с выводом текста и графики
      и подключение его согласно программе?

  17. Добрый день. Подскажите, можно ли «подружить» msp430g2231(14 ножек) с дисплеем WG12864(20 ножек)? есть ли возможность использовать 4-х битную передачу данных?

    1. Наверняка. Если портов хватает, то не вижу проблем. С другой стороны может быть конфликт уровней 3.3-5 вольт (контроллер скольки вольтовый?), но он решается.

      1. Контроллер на 3.3 В работает, у дисплея мин. 3.5 В. Возникнет конфликт? или это уже надо «вживую» смотреть.
        Проблема была в нехватке ножек у контроллера для управления дисплеем. Можно использовать, как выход, сдвиговый регистр 74HC595? Чем это грозит? Сильно скажется на быстродействии?

        1. Да, надо разбираться с соглассованием уровней. Ставить делители и подобные ухищрения.

          Можно, но быстродействие упадет раз в ~20 раз. При той же загрузке контроллера. Думаю вам куда проще будет использовать дисплей со SPI интерфейсом. Он требует всего 4 провода максимум.

  18. DI, не подскажешь в чём может быть ошибка (кроме ДНК):
    при вызове функции установки пикселя выводится столбец пикселей.
    компилил в AVR Studio 5
    индикатор (LGM12641BS1R) подключаю к атмеге 128.
    вот такая реакция на PIXEL (0,0);
    http://imageshack.us/photo/my-images/854/protn.jpg/

    никаких элементов кроме жки и контроллера на схеме нет.

    1. Где то у тебя маска прохерилась. Т.е. вместо установки пикселя (одного бита) вгоняется байт. Ну и это, протеус нах. Делай вживую.

  19. При работе с графическими модулями, возникают весьма существенные
    трудности/неудобства.
    Они связаны с несовершенством имеющихся в наличии программ, которые
    рассчитанны на работу с графическими модулями.
    В частности, такие трудности/неудобства возникают на стадии
    «конструирования» как «кадра», так и его элементов.
    На сайте http://ikarab.narod.ru имеются программы KS0108 существено
    помогающие при программировании контроллеров PIC.
    ВОПРОС: МОЖНО ЛИ ДОДЕЛАТЬ ДЛЯ ТОГО ЧТОБЫ У KS0108 БЫЛА ВОЗМОЖНОСТЬ РАБОТАТЬ С ATmega ?

  20. Хорошая статья все работает отлично но вот только не могу вывести картинку
    ,картинка записана во flash память .Я читаю адрес массива в переменную «а»
    char a=pgm_read_byte(&(lol1[0])); вставляю в функцию
    BLOCK(1,1,1024,0×0054);но результата 0 .В чем может быть проблема?

  21. Ценник в 500 рублей — совершенно конский. За 300 можно купить цветной LCD с SPI интерфейсом для нокии 6100 — 128х128, 65536 цветов. Даташит на контроллер — есть. Более того, олимекс даже кучу плат на полном серьезе с ними выпускает. Как раз по этой самой причине — нет смысла делать допотопно выглядящий девайс когда можно сделать куда симпатичнее и функциональнее за меньшие деньги.

    1. Смотря куда. В развоую самоделку может и так, а в серийное устройство я ставлю то, что без проблем можно купить, а потом без колхоза установить.

  22. А кто нибудь из вас знает как надо запрограммировать Atmega2560, чтобы подключить к нему TFT дисплей на контроллере SSD1963, SSD1289 или XG7100 ?

  23. Подскажи пожалуйста, какие есть визуальные средства редактирования матриц для LCD ??? Я имею ввиду, чтобы bin файл отображался как на рисунке в виде квадратиков 1 и 0. То есть, чтобы можно было нарисовать визуально в этой матрице шрифт текста или эмблемку какую мне необходимо ??? И сразу было видно как она будет смотреться на дисплее … )

  24. DI HALT немного не понял с системой команд точнее не совсем понятно название первого столбца RS может быть опечатка и надо «DI»

  25. Привет всем! Это мой первый пост на этом замечательном сайте. Я всего несколько месяцев, как начал программировать на языке Си, ну, и в качестве очередного эксперимента написал небольшую библиотеку для МК PIC24F, работающую с ЖК индикаторами на базе графического контроллера KS0108. Полагаю, при желании не составит труда перенести ее и на архитектуру AVR. Итак, есть проект для Proteus-а и пара небольших примеров, демонстрирующих возможности этого рукобл… делия. Могу выложить их (правда, не знаю, как это сделать… :-) ).

  26. Обьясните мне как так получилось что на моем дисплее обратная полярность по питанию??? Взял распиновку именно с этой стати, подключил и микросхемы дисплея сразу закипели. Когда начал выяснять в чем проблема то оказалось 1-й вывод это плюс а второй-минус а у Вас в статье наоборот. В итоге дисплей вышел со строя!!!

    1. Распиновку надо всегда брать не со статей, а с конкретного даташита. Т.к. Там полно подверсий с разными включениями и кто знает какой у вас.

  27. У меня на руках дисплей от плоттера с аналогом KS0108 — s6b0108. Выводы CS1 CS2 сидят на земле. Как быть? И что за вывод Di на схеме?

    1. CS1 CS2 сидят на земле — значит выбраны оба внуьренних контролера.
      D/I — Данные/команда. Логический уровень на этом выводе определяет предназначение кода на шине данных. 1 — данные, 0 — команда.

      1. какой-то год спустя…
        С CS-ами понял: у s6b0108 есть CS1B CS2B CS3. Выбор активного идет как L L H. Вот первые два уже L, а третьим собственно и выбираем. Это так, к слову…
        А вот линии D/I нет. Или правильней сказать, я не врубился, как она подключена. Ноги ks0107 и s6b0107 одинаковые, но ни там ни там нет D/I. Какая она должна быть?

  28. Есть плата с mega32, но ноги у неё запаяны наоборот т. е. DB0 к PD7, DB1 к PD6 и т. д. Изображение на экране высвечивается неправильно, что делать?

  29. Подключаю аналогичный ЖКИ к стм32, в общем то наверное это не важно. Суть такова, что не сбрасывается бит BUSY, т.е при вычитке байта состояния этот бит всегда в 1. Что не нравится индикатору? Из-за чего такое может быть?

  30. Не то что бы я вам не доверяю, но очень люблю читать официальную документацию, а при поиске ks0107/ks0108 можно найти только описание непосредственно чипов, а при поиске WG12864 только физические параметры дисплея.
    Где описан протокол? Или таких доков нет?

  31. Добрый день всем!
    Задача:
    Перевести код под CVAVR.
    Проблема:
    Уже все переделал кроме этой строки:
    LCD_WR_DATA(pgm_read_byte(addr),CSS); // Пишем туда данные прям из флеша (таблица символов).
    Ругается на pgm_read_byte(addr) — это что такое? Получение адреса?

    Подскажите пожалуйста как можно по другому сделать.

    1. Это чтение данных из флеша. Чисто GCCшный подход. У CVAVR будет что то другое. Ищи как делается в CVAVR чтение данных из памяти программ и делай тем способом.

  32. Вопросик, у знакоситензирующих экранов типа 1604 и графических 12864, данные постоянно регенерируются на экране из буфера самого экрана, т.е. один раз записал в буфер данные выводимые на экран и он сам дальше отображает их, пока не запишешь новые данные для вывода на экран? Или их как у больших RGB TFT 800×640 нужно постоянно с определенной частотой выводить данные обновляя одну и туже картинку?

Добавить комментарий

Ваш e-mail не будет опубликован.

Перед отправкой формы:
Human test by Not Captcha