Часть вторая. Как я вывожу символы на дисплей.
Так как наш дисп графический, то это значит что мы сами должны организовывать прорисовку символов на экране. На первый взгляд сложно. Оно и в самом деле не очень просто, но тяжело в ученьи-легко в бою: когда мы всё настроим то выводить информацию на дисп будет не сложнее чем на банальный 16х2.
Нам понадобится файл со шрифтом, этот файл определяет какие символы как будут изображаться. Простейший шрифт - 5х7. Это значит по вертикали 7 точек, по горизонтали 5. Шрифт не слишком красивый но вполне читаемый. Скажу больше - я пробовал рисовать в ширину 3 точки - тоже читаемо, но очень коряво.
Как в файле шрифта кодируется символ. Каждому символу (в случае 5х7) отводится 5 байтов. Первый байт даёт нам левый столбец, второй - второй и 5й байт - правый столбец. Младший бит - верхняя точка столбца. Старший бит (7) - нижняя точка. Обычно он равен 0 - он служит как бы пробелом между строками, так что реально изображает символ максимум бит 6.
Что нам теперь нужно. Нам нужно вывести по очереди эти 5 байтов на дисплей, напомню первый байт слева, справа последний. Но если просто отправить байт в дисплей то ничего не выйдет. Дело в том что в файле шрифта каждый бит каждого байта означает отдельный пиксель (0-не светится, 1-светится). А нам нужно для того что бы пиксель светился отправить 3 байта. Видите? Нам нужно один бит превратить в 3 байта.
Я делаю так:
void CFB(unsigned char datf, unsigned char R, unsigned char G, unsigned char B)
{
if(datf & (1 << 0))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 1))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 2))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 3))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 4))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 5))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 6))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
if(datf & (1 << 7))
SDLCDcolor(R,G,B); else SDLCDcolor(fonR,fonG,fonB);
}
Что происходит: мы передаём процедуре байт прочитанный из файла шрифта и цвет которым он должен отобразиться и один байт передётся 8х3 байтов. Переменные fonB..fonR - это у меня глобальные переменные которые означают цвет фона. Если цвет фона изменять не планируется, то их можно заменить конкретными цифрами.
Можно конечно упростить сделав цикл, хотите сделайте.
Так вот, мы передаём 5 байтов из шрифта - и - на экране символ!
Давайте передадим их:
void PrintL(unsigned int num, unsigned char R, unsigned char G, unsigned char B)
{
num=num*5;
temp=pgm_read_byte(&(Font_5x8[num+0]));
CFB(temp,R,G,B);
temp=pgm_read_byte(&(Font_5x8[num+1]));
CFB(temp,R,G,B);
temp=pgm_read_byte(&(Font_5x8[num+2]));
CFB(temp,R,G,B);
temp=pgm_read_byte(&(Font_5x8[num+3]));
CFB(temp,R,G,B);
temp=pgm_read_byte(&(Font_5x8[num+4]));
CFB(temp,R,G,B);
CFB(0,fonR, fonG, fonB);
}
Мы передаём процедуре код символа и цвет.
Но мы ещё не задали куда нужно выводить! Напрмер так:
void DSAT(unsigned int X, unsigned int Y)
{
//---Задаём область вывода текста (8 пикселей в высоту)---
LCDCommand(0x2A); //Команда по Y координате
temp=(Y >>

& 0xff;
LCDData(temp); //Данные начала Y координат (старший байт)
temp=Y & 0xff;
LCDData(temp); //младший байт
Y=Y+7;
temp=(Y >>

& 0xff;
LCDData(temp); //Данные конца Y координат (старший байт)
temp=Y & 0xff;
LCDData(temp); //младший байт
//----------
LCDCommand(0x2B); //Команда по Х координате
temp=(X >>

& 0xff;
LCDData(temp); //Данные начала X координат (старший байт)
temp=X & 0xff;
LCDData(temp); //младший байт
temp=(X >>

& 0xff;
LCDData(0x1); //Данные конца X координат (старший байт)
LCDData(0x90); //младший байт
}
Тут мы вызывем процедуру с координатами верхнего левого угла символа. Далее вычисляется и передаётся в дисплей нижний край области вывода, рассчётом правой границы я не стал заниматься - я задаю по максимуму (край дисплея), хватит всегда.
Теперь мы можем выводить символы на экран задав область вывода и передавая символ за символом. Но так уныло и не красиво. Я делаю красивее. Глубинной сути этого явления я не понял, но оно работает, хоть и пишет предупреждения.
Процедура такая:
void showstr(unsigned char *s, unsigned int X, unsigned int Y, unsigned char R,unsigned char G,unsigned char B)
{
D_PORT &= ~(1 << CS); //Ноль
DSAT(X, Y);
LCDCommand(0x2C); //Команда записи в память дисплея Что
//---------- собственно выводим текст-------------------------
while(*s != 0) PrintL(*s++,R,G,B);
D_PORT |= 1 << CS; //Единица
}
Мы вызываем задавая координаты вывода и цвет.
Но это ещё не все, пользуемся процедурой так:
showstr("Паяльника нет!",3,3,255,255,255); //Текст, начало X Y
Красиво жутко.
Примечание. Если мы будем делать так как я всё описал, используя шрифт 5х8 то получим микроскопические буквочки которые нелегко читать, так как пиксели у нашего диспа очень мелюсенькие. Что делать? Если памяти программ мало (ведь в ней кроме собственно программы будет храниться и шрифт) то можно программно растягивать символы - один бит шрифта превращать не в 3 байта, а в 6 (передаём R G B R G B - получается по вертикали 2 одинаковых по цвету пикселя) и а так же выводить каждый байт шрифта дважды (получатся 2 одинаковых столбца).Но тогда символы будут корявоватые. А если памяти достаточно то можно использовать шрифты крупнее, например 12х16. Тогда символы будут красивые и не маленькие. Но тогда надо усложнить процедуры. В прилагаемом проекте я использовал как раз такой шрифт.
Просьба за мой проект ногами не пинать, это моя вторая программа на С. Этот проект - велоспидометр с одометром и часами (часы правда работают через раз, пока не понял почему), делал сыну, дисплей S5230, МК ATMEGA32. Датчик - датчик холла на вилке и 2 магнита на спицах.

Вышел из себя.
Пришел в себя.
Ушел в себя.
И решил больше сегодня никуда не ходить