Вывод символов и строк на TFT дисплей, на примере SSD1289.
Первым делом хотелось бы сказать, что у дисплея меньшая сторона - Х, большая сторона - У.
В прошлой статье мы рассмотрели как, как произвести инициализацию дисплея, в этой будем учиться выводить на дисплеи символы и строки. Начнём с символов.
Символы представляют собой набор точек, закрашенных в определённом порядке.
Для вывода на экран точки необходимо выполнить следующую последовательность действий:
Таким образом, простейший код для вывода точки на дисплей будет выглядеть следующим образом:
Дальше, для вывода следующей точки, посылаем только кодировку цвета, которым хотим закрасить следующую ячейку, а SSD1289 сам будет шагать по ячейкам, по выбранному нами ранее алгоритму. Для того чтобы освежить память выложу скрин даташита, зелёным отмечен выбранный нами режим.
Точка, которую мы вывели на дисплей очень маленькая и плохо видна, хорошо было бы увеличить её размер. Например, чтобы она выглядела так.
Главное, надо понимать, что точка большого размера представляет собой квадрат. Давайте напишем код для вывода точки заданного размера.
Для дальнейшего использования удобно выделить код для выбора точки в видеоОЗУ, в функцию.
Теперь когда мы научились рисовать точку, нам не составит труда одной большой точкой закрасить экран))) Шутка, экран прямоугольный, а точка квадратная поэтому не получится.
Но мы можем закрасить экран множеством маленьких точек, для этого надо установить курсор в начало экрана и в цикле 76800 раз отправить цвет, которым хотим закрасить экран. SSD1289 сам по выбранному нами ранее алгоритму закрасит весь экран, а 76800 = 320х240, то есть количество точек на экране.
Теперь можно переходить к буквам. Каждая буква размером 8х8 представляет собой массив из 8 элементов, на рисунке ниже видно как формируется массив.
Для того чтобы вывести букву А, надо построчно выводить элементы массива. Для удобства все буквы вместе сложены в один большой массив и хранятся во флеше контроллера, на что указывает атрибут PROGMEM.
В простейшем виде функция, отрисовывающая на экране, символы выглядит следующим образом.
Давайте разберёмся как она работает. На первой итерации когда j=0 и i=0 курсор устанавливается в координаты, которые мы передали в функцию. Итерационная переменная j определяет смещение курсора по оси ОХ, то есть вниз. Итерационная переменная i определяет смещение курсора по оси ОУ, то есть вправо. Дальше с помощью
(pgm_read_byte(&sim[j])
из флеша извлекается нулевой элемент массива. У этого элемента, смещением в последнюю позицию помещаем интересующий нас бит
((pgm_read_byte(&sim[j]))>>(7-i))
теперь с помощью операции "побитового и" определяем чему он равен, нулю или единице.
0x01&((pgm_read_byte(&sim[j]))>>(7-i))
Если он равен единице рисуем точку соответствующую цвету символа, иначе точку цвета фона. Помните как мы рисовали большую точку, заменяя её квадратом? Также можно сделать здесь, вместо одной точки рисовать квадрат произвольного размера. Тогда конечная функция для отрисовки символа на дисплее будет выглядеть следующим образом.
Далее, из букв не составляет труда складывать слова.
А вот и функция для вывода строк.
В этой функции есть один нюанс - это нахождение необходимого символа в таблице, за который отвечает следующий кусочек кода.
simbols+((pgm_read_byte(&string[k]))-32)*8
Сначала мы получаем интересующий нас символ из строки, с помощью следующей конструкции, где к - номер символа в строке.
&string[k]
Допустим мы получили букву А. Так как символы в строке хранятся в виде ascii кода, для буквы 'А' он равен 65. В нашем массиве буква 'А' находится на 34 строке, значит для того, чтобы найти интересующую нас букву мы должны от 65 отнять 32, получим 33 или смещение в строках от начала массива и умножим его на количество элементов в строке - 8. Теперь если мы к началу массива прибавим, вычисленное смещение, получим первый элемент для отрисовки буквы А.
Пожалуй на этом всё, в следующей статье мы будем учиться рисовать геометрические фигуры.
Проект для Atmega16 в Atmel Studio 6.2 в архиве
В прошлой статье мы рассмотрели как, как произвести инициализацию дисплея, в этой будем учиться выводить на дисплеи символы и строки. Начнём с символов.
Символы представляют собой набор точек, закрашенных в определённом порядке.
Для вывода на экран точки необходимо выполнить следующую последовательность действий:
- выставляем координату Х ячейки в регистре R4E;
- выставляем координату У ячейки в регистре R4F;
- выбираем регистр R22, то есть говорим: “Сейчас будем писать в видеоОЗУ”;
- посылаем кодировку цвета, который хотим вывести в данной ячейке;
Таким образом, простейший код для вывода точки на дисплей будет выглядеть следующим образом:
Lcd_Write_Reg(0x004e, x);
Lcd_Write_Reg(0x004f, y);
Lcd_Write_Index(0x0022);
Lcd_Write_Data(color);
Дальше, для вывода следующей точки, посылаем только кодировку цвета, которым хотим закрасить следующую ячейку, а SSD1289 сам будет шагать по ячейкам, по выбранному нами ранее алгоритму. Для того чтобы освежить память выложу скрин даташита, зелёным отмечен выбранный нами режим.
Точка, которую мы вывели на дисплей очень маленькая и плохо видна, хорошо было бы увеличить её размер. Например, чтобы она выглядела так.
Главное, надо понимать, что точка большого размера представляет собой квадрат. Давайте напишем код для вывода точки заданного размера.
// size — размер точки, х и у — координаты верхнего левого угла точки, color – цвет точки.
void Draw_Point(uint8_t size,uint16_t x,uint16_t y,uint16_t color)
{
uint8_t j, i=0; //итеррационные переменные
for(j=0; j<size; j++) // в этом цикле выставляется начало коордтнат горизонтальной линии
{
Lcd_Write_Reg(0x004e, x+j);
Lcd_Write_Reg(0x004f, y);
Lcd_Write_Index(0x0022);
for(i=0; i<size; i++) // в этом цикле рисуется горизонтальная линия
{
Lcd_Write_Data(color);
}
}
}
Для дальнейшего использования удобно выделить код для выбора точки в видеоОЗУ, в функцию.
void Set_Cursor(uint16_t x_kur, uint16_t y_kur)
{
Lcd_Write_Reg(0x004e, x_kur);
Lcd_Write_Reg(0x004f, y_kur);
Lcd_Write_Index(0x0022);
}
Теперь когда мы научились рисовать точку, нам не составит труда одной большой точкой закрасить экран))) Шутка, экран прямоугольный, а точка квадратная поэтому не получится.
Но мы можем закрасить экран множеством маленьких точек, для этого надо установить курсор в начало экрана и в цикле 76800 раз отправить цвет, которым хотим закрасить экран. SSD1289 сам по выбранному нами ранее алгоритму закрасит весь экран, а 76800 = 320х240, то есть количество точек на экране.
void TFT_Clear(uint16_t color)
{
uint32_t index=0;
Set_Cursor(0,0);
for(index=0; index<76800; index++)
{
Lcd_Write_Data(color);
}
}
Теперь можно переходить к буквам. Каждая буква размером 8х8 представляет собой массив из 8 элементов, на рисунке ниже видно как формируется массив.
Для того чтобы вывести букву А, надо построчно выводить элементы массива. Для удобства все буквы вместе сложены в один большой массив и хранятся во флеше контроллера, на что указывает атрибут PROGMEM.
В простейшем виде функция, отрисовывающая на экране, символы выглядит следующим образом.
void Draw_Simbol(uint16_t x, uint16_t y, uint16_t color, uint16_t phone, const uint8_t *sim)
{
volatile uint8_t j, i; //переменные размерности по строкам и столбцам
for(j=0; j<8; j++) //для 8-ми строк по x
{
Set_Cursor(x+j,y); //устанавливаем курсор
for(i=0; i<8; i++) //для 8-ми столбцов по y
{
if(0x01&((pgm_read_byte(&sim[j]))>>(7-i))) //если 1 - пишем точку цвета символа
{
Lcd_Write_Data(color);
}
else //если 0 - пишем точку цвета фона
{
Lcd_Write_Data(phone);
}
}
}
}
Давайте разберёмся как она работает. На первой итерации когда j=0 и i=0 курсор устанавливается в координаты, которые мы передали в функцию. Итерационная переменная j определяет смещение курсора по оси ОХ, то есть вниз. Итерационная переменная i определяет смещение курсора по оси ОУ, то есть вправо. Дальше с помощью
(pgm_read_byte(&sim[j])
из флеша извлекается нулевой элемент массива. У этого элемента, смещением в последнюю позицию помещаем интересующий нас бит
((pgm_read_byte(&sim[j]))>>(7-i))
теперь с помощью операции "побитового и" определяем чему он равен, нулю или единице.
0x01&((pgm_read_byte(&sim[j]))>>(7-i))
Если он равен единице рисуем точку соответствующую цвету символа, иначе точку цвета фона. Помните как мы рисовали большую точку, заменяя её квадратом? Также можно сделать здесь, вместо одной точки рисовать квадрат произвольного размера. Тогда конечная функция для отрисовки символа на дисплее будет выглядеть следующим образом.
void Draw_Simbol ( uint16_t x, uint16_t y, uint16_t color, uint16_t phone, const uint8_t *sim,
uint8_t size)
{
volatile uint8_t j, i, k, p ;
for( j=0; j<8; j++) //вывод 8-ми строк по x
{
for( k=0; k< size; k++) //size - размер точки
{
//устанавливаем курсор в начало строки которую будем отрисовывать
Set_Cursor(x+(j*size)+k, y);
for( i=0; i<8; i++) //вывод 8-ми столбцов по y
{
//если в массиве символа 1 - пишем точку цвета символа size раз
if(0x01 & ((pgm_read_byte(&sim[j])) >> (7 - i)))
{
for( p=0; p< size; p++) Lcd_Write_Data(color);
}
//если в массиве символа 0 - пишем точку цвета фона size раз
else
{
for(p=0; p< size; p++) Lcd_Write_Data(phone);
}
}
}
}
}
Далее, из букв не составляет труда складывать слова.
А вот и функция для вывода строк.
void Draw_String (uint8_t size,uint16_t start_x,uint16_t start_y,uint16_t color,uint16_t phone,const uint8_t *string)
{
// максимальное количество знакомест по х и у, промежуточные координаты, счётчик символов в строке
uint16_t max_x, max_y, x1, y1, k = 0;
if(size > 5) size=5; //размер точки более 5х5 не имеет смысла
max_y = 320/(size*8); //mах кол-во знакомест по y
max_x = 240/(size*8); //max кол-во знакомест по x
for(x1 =start_x; x1 < max_x; x1++)
{
for(y1 =start_y; y1 < max_y; y1++)
{
//выводим символ заданных параметров из строки
Draw_Simbol(x1*8*size,y1*8*size,color,phone,simbols+((pgm_read_byte(&string[k]))-32)*8,size);
//если кол-во символов превысит максимальное в строке - выходим из функции
if(k++ > (strlen_P (string))-2) return;
}
}
}
В этой функции есть один нюанс - это нахождение необходимого символа в таблице, за который отвечает следующий кусочек кода.
simbols+((pgm_read_byte(&string[k]))-32)*8
Сначала мы получаем интересующий нас символ из строки, с помощью следующей конструкции, где к - номер символа в строке.
&string[k]
Допустим мы получили букву А. Так как символы в строке хранятся в виде ascii кода, для буквы 'А' он равен 65. В нашем массиве буква 'А' находится на 34 строке, значит для того, чтобы найти интересующую нас букву мы должны от 65 отнять 32, получим 33 или смещение в строках от начала массива и умножим его на количество элементов в строке - 8. Теперь если мы к началу массива прибавим, вычисленное смещение, получим первый элемент для отрисовки буквы А.
Пожалуй на этом всё, в следующей статье мы будем учиться рисовать геометрические фигуры.
Проект для Atmega16 в Atmel Studio 6.2 в архиве
Похожие статьи