Управление контроллером графического ЖКИ индикатора T6963C на примере индикатора PG24064-E/F.
ОКОНЧАНИЕ
Выведем для примера на дисплей цифру "4" в третий столбец четвертой строки. Код этой цифры в знакогенераторе контроллера будет 0x14. Записать его нужно в ОЗУ по адресу 0x1700+0x3*0x28+0x2=0x177a. Сделать это можно следующим образом:
while ((GetStatusLCD()&0x03)!=0x03); //Поместить в указатель адреса значение 0x177a
Send8LCD(0,0x7a); //младший байт
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,0x17); //старший байт
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0x24); //команда
while ((GetStatusLCD()&0x03)!=0x03); //Вывод знака
Send8LCD(0,0x14); //запись кода числа "4"
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0xC0); //команда
Как видно, для записи одного знака требуется сначала установить указатель адреса на требуемую позицию, а затем вывести сам знак. После этого при использовании данной команды указатель адреса будет инкрементирован. Такая возможность позволяет последовательно заполнять ОЗУ данными без установки указателя адреса (например, производить вывод строк символов). Так же существуют команды записи байта с декрементом или без изменения указателя.
В том случае, если требуется вывести относительно большой массив данных, то при использования вышеприведенных команд после каждого байта будет необходимо передавать команду записи, что значительно замедляет вывод. Поэтому в контроллере существует режим автозаписи (авточтения), позволяющий один раз перейти в этот режим, а затем производить непрерывную передачу (прием) данных без использования каких-либо команд. Ниже приведен пример вывода строки
"0123456789" в этом режиме. Строка выводится, начиная с первого столбца первой строки (адрес в ОЗУ 0x1700).
while ((GetStatusLCD()&0x03)!=0x03); //Поместить в указатель адреса значение 0x1700
Send8LCD(0,0x00); //младший байт
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,0x17); //старший байт
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0x24); //команда
while ((GetStatusLCD()&0x03)!=0x03); //Включение режима автозаписи
Send8LCD(1,0xb0);
//Далее запись символов
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x10);//"0"
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x11);//"1"
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x12);//"2"
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x13);//"3
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x14);//"4
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x15);//"5
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x16);//"6
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x17);//"7
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x18);//"8
while ((GetStatusLCD()&0x08)!=0x08);
Send8LCD(0,0x19);//"9
while ((GetStatusLCD()&0x08)!=0x08);//Выключение режима автозаписи
Send8LCD(1,0xb2);
Как было указано выше, графическая информация при FS=1 выводится по 6 точек в байте. Младший бит соответствует левой точке, установленный бит - включенной точке. Запись байта в графическую область производится точно также как и в текстовую. Поэтому, если в приведенном выше примере вывода символа "4" указатель адреса установить в графической области ОЗУ (например 0x0000), то вместо символа "4" появится линия из шести точек, которые будут включены или погашены в следующем порядке (слева направо): погашена, погашена, включена, погашена, включена, погашена.
Помимо вывода графики побайтно также существует возможность установки или сброса одного бита в байте по заданному адресу. Это позволяет управлять отдельными точками на экране. Ниже приведена функция, позволяющая засвечивать или гасить отдельный бит по заданному адресу.
while ((GetStatusLCD()&0x03)!=0x03);
//Вывод точки.
if (bt)
Send8LCD(1,(0xf8|(5-(X-(X/6)*6))));
else
Send8LCD(1,(0xf0|(5-(X-(X/6)*6))));
}
В этой функции используется функция установки указателя адреса, позволяющая выполнять эту операцию в одной строке, что облегчает читаемость программы. Вот ее текст:
void SetAddrLCD(unsigned int addr)
{
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,(unsigned char)addr);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,(unsigned char)(addr>>8));
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0x24);
}
Для применения функции PutPixelXYLCD(X, Y, bt) в первой переменной необходимо задать столбец и строку точки (нумерация с нуля) и, в том случае, если точку необходимо погасить - нуль, а если засветить - не нуль. Ниже приводится еще одна функция, позволяющая аналогично выводить текст:
SetAddrLCD((unsigned int)(LCD_TextHome)+(unsigned int)X+(unsigned int)Y*0x28);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,bt);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0xC4);
}
Во всех вышеприведенных примерах индикатор использовался одновременно как в текстовом,
так и в графическом режиме. Однако, если графика не требуется, то ее можно отключить, а вместо нее использовать так
называемый режим текстовых аттрибутов. В этом режиме для каждого символа текста можно задать один из нескольких способов
его отображения. Для включения этого режима необходимо командой "MODE SET" задать режим "Text Attribute", а командой
"DISPLAY MODE" - включить как текст, так и графику. Чтобы задать текстовый аттрибут для символа, находящегося в текстовой
области ОЗУ, необходимо записать соответствующий байт в графическую область ОЗУ с тем же смещением. Например, выведем
негативную мигающую цифру "7" по адресу 0x1710. Для того, что бы она мигала необходимо по адресу 0x0010 записать значение
0x0d.
while ((GetStatusLCD()&0x03)!=0x03);//Задаем режим текстовых аттрибутов
Send8LCD(1,0x84);
while ((GetStatusLCD()&0x03)!=0x03);//Задаем режим отображения графики и текста
Send8LCD(1,0x9f);
SetAddrLCD(0x1710);
while ((GetStatusLCD()&0x03)!=0x03); //Вывод знака
Send8LCD(0,0x17); //запись кода числа "7"
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0xC0); //команда
SetAddrLCD(0x0010);
while ((GetStatusLCD()&0x03)!=0x03); //Вывод аттрибута
Send8LCD(0,0x0D);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0xC0); //команда
И последнее, что будет рассмотрено в данной статье - это способы загрузки пользовательских шрифтов. Шрифты загружаются в текстовую область ОЗУ. Начальный адрес для загрузки шрифтов не должен перекрывать область вывода текстовой информации (в нашем случае это 0x1700+0xff). Пусть для примера начальным адресом будет 0x1c00. Перед загрузкой шрифтов необходимо задать так называемое смещение, которое зависит от области памяти, в которую выводятся шрифты. Ниже приведена таблица зависимости смещения от адресов в памяти.
Смещение
Адреса ОЗУ
0x00
0x0000 - 0x07ff
0x01
0x0800 - 0x0fff
0x02
0x1000 - 0x17ff
0x03
0x1800 - 0x1fff
...
...
0x1f
0xf800 - 0xffff
Как видно из таблицы, в рассматриваемом примере смещение должно быть равно 0x03.
Затем, после установки смещения задается начальный адрес (0x1c00) и загружаются знаки. В том случае, если командой
"MODE SET" был выбран режим "Internal CG ROM mode", можно будет ввести только 128 знаков, которые будут доступны начиная
с 0x80 адреса знакогенератора, а по адресам 0x00-0x7f будут находиться знаки ПЗУ контроллера. В этом случае байту 0x80,
записанному в текстовую область контроллера будет соответствовать знак, находящийся по адресу 0x1C00. При выборе режима
"External CG RAM mode" пользователь может задать 256 символов, которые полностью заменят знаки, находящиеся в ПЗУ контроллера. Для
примера загрузим в контроллер букву "Д" в режиме "Internal CG ROM mode". В двоичном виде она будет выглядеть так:
Загрузка начинается с верхней строки. Далее приводится текст примера загрузки и вывода на индикацию буквы "Д".
while ((GetStatusLCD()&0x03)!=0x03);//Задаем смещение
Send8LCD(0,0x03);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,0x00);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0x22);
SetAddrLCD(0x1c00);//Устанавливаем начальный адрес для загрузки шрифта
SendByteIncLCD(0x0f);//Загрузка буквы
SendByteIncLCD(0x05);
SendByteIncLCD(0x05);
SendByteIncLCD(0x09);
SendByteIncLCD(0x09);
SendByteIncLCD(0x11);
SendByteIncLCD(0x1f);
SendByteIncLCD(0x11);
SendCharXYLCD(0,0,0x80);//Вывод буквы в нулевой столбец нулевой стоки
где SendByteIncLCD(bt) - функция загрузки байта с инкрементом указателя адреса:
void SendByteIncLCD(unsigned char bt)
{
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(0,bt);
while ((GetStatusLCD()&0x03)!=0x03);
Send8LCD(1,0xC0);
}
На этом рассмотрение основных функций контроллера T6963C можно считать законченным,
хотя помимо описанных у него имеются еще и другие возможности. Однако на взгляд автора давать их полное описание
смысла не имеет, все можно найти в документации.