Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

Продолжаю ковырять графический дисплей (GLCD), теперь можно с уверенностью сказать, что с выводом русского алфавита на дисплеи с контроллером ks0108, более менее все понятно.

В целом ничего нового, все буквы хранятся в виде массива, аналогично картинкам. Массив выглядит так:

flash unsigned char font[]={
0x05,
0x07,
0x20,
0xC0
#ifndef _GLCD_DATA_BYTET_
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
....
#else
0x00,0x00,0x00,0x00,0x00,
....
#endif
};

Первый элемент массива — ширина символов, второй — высота символов, третий — номер первого символа по таблице кодировки — ASCII. Четвертый — количество символов. Далее идет описание графики, как она хранится, было написано в предыдущей статье.

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

Сам алфавит можно нарисовать в LCD Vision, но из за ограничений бесплатной версии  выглядит это все весьма утомительно.glcd_vision

Работа с текстом сложностью не отличается, для вывода строки используется функция

glcd_outtextxy(25,30,"ПРИВЕТ");

Первый аргумент — координата по Х, второй — координата по У. Далее пишите желаемый текст и наслаждаетесь результатом. Координаты отсчитываются относительно верхнего левого угла. Для вывода русского алфавита, нужно подключить библиотеку, в которой содержится массив с графикой. Библиотека лежит в папке с проектом под именем font5x7rus.h. Пока что организован вывод только ПРОПИСНЫХ букв, строчные чуть позднее добавлю.

По прошивке особо комментировать нечего, вместо символа можно написать его номер, т.е. ‘А’ будет равнозначно 0xC0. Чтобы разобраться в этом посмотрите ASCII. На других дисплеях пока не тестировал, но на ks0108 вроде работает исправно.

#include <mega8.h>
#include <glcd.h>
#include <font5x7rus.h> //библиотека с русскоязычной графикой
 int i=0,x=0, y=0;
 
void main(void)
{
GLCDINIT_t glcd_init_data;
 
PORTB=0x00;
DDRB=0x00;
 
PORTC=0x00;
DDRC=0x00;
 
PORTD=0x00;
DDRD=0x00;
 
// Specify the current font for displaying text
glcd_init_data.font=font5x7;        //font5x7;
glcd_init(&glcd_init_data);
 
while (1)
      {
          for(i=0;i<33;i++) //выводим все буквы алфавита
          {
              if(i==20) //после 20 буквы переходим в 0, чтобы на залезть за экран.
              {
                 y=10;
                 x=0;                
              }
           glcd_putcharxy(x*6,y,0xC0+i);
           x++;
          }
          y=0; 
          x=0;
          glcd_outtextxy(25,30,"AVR-START.RU"); //выводим строку в указанной координате
          glcd_outtextxy(15,40,"ЭЛЕКТРОНИКА ДЛЯ"); 
          glcd_outtextxy(30,50,"НАЧИНАЮЩИХ");
      }
}

Результат:

glcd_rus

Прошивку можно скачать здесь:

Update: поясняющая картинка, как получаются буквы
alfabet

51 комментарий: Урок 18.3. Вывод русскоязычного текста на GLCD

  • А как выводить на экран БОЛЬШИЕ шрифты, размером, скажем 12Х16?

  • придется рисовать шрифт, а выводить также

  • Получилось с БОЛЬШИМИ шрифтами. Теперь задача с водится к тому, как одновременно использовать шрифт 5х7 и 12х16?

    Пробовал следующее:
    glcd_init_data.font=font12x16; //включаем шрифт размером 12х16
    glcd_init(&glcd_init_data);

    show_RPM(); //процедура, которая использует БОЛЬШИЕ цифры

    glcd_init_data.font=font5x7; //включаем стандартный шрифт 5х7
    glcd_init(&glcd_init_data);

    Но инициализация работает очень медленно и такой метод не подходит. Как по другому реализовать такую функциональность?

  • Возможно так заработает

    GLCDINIT_t glcd_init_data;
    GLCDINIT_t glcd_init_data1;
     
    // Specify the current font for displaying text
    glcd_init_data.font=font5x7;        //font5x7;
    glcd_init(&glcd_init_data);
    
    glcd_init_data.font=font12x16;        //font12x16;
    glcd_init(&glcd_init_data1);
    
  • ув. админ подскажи как свзязать функцию
    glcd_outtextxy(25,30,»AVR-START.RU»); //выводим строку в указанной координате
    glcd_outtextxy(15,40,»ЭЛЕКТРОНИКА ДЛЯ»); с руским и английским шрифтом

    ты делал шрифт на два алфавита? или как

  • запарился в lcdvision когда создавал фонт

  • латиница там есть, я только русские добавлял

  • «Свехнаглая» просьба, можно выложить библиотеку font5x7rus.h. не только с заглавными но и с маленькими буквами. Боюсь я сам не справлюсь. Или подскажите где можно скачать. Если вас конечно не затруднит.

  • в конце статьи добавил картинку, слева двоичное число, справа его hex коды.

  • LCDVision генерить для любого ЖКД. Если кому надо, скину на почту.

  • А как выводить цифры в «динамическом» режиме например при отображении температуры, напряжения, или просто часов?

  • А пример обучения с цветным сенсорным дисплеем, например ILI9325, в будущем рассмотрен будет?

  • скорее всего будет пример на stm32f429, когда появится возможность

  • Подскажите как использовать переменную для вывода букв или цифр на LCD из шрифта, что вроде как вы использовали команду glcd_putcharxy(x*6,y,0xC0+i), надеюсь я правильно выразил свою мысль.

  • нужно преобразовать переменную в текст, например через sprintf

  • Всем здравствуйте. подскажите с помощью какой функции сделать инверсным шрифт? вроде бы во всем разобрался сам. остался этот вопрос.

  • В функциях библиотеки этого нет, поэтому придется дописывать руками.

  • Уважаемый Admin
    Подключил к Atmega8A графический дисплей на контроллере KS0108
    Помогите вывести переменные на экран, с текстом вроде ясно, а как с переменными?! Прочитал кучу материала, вроде как надо преобразовывать число в строку через sprintf, но ничего не получается.
    Вот кусок кода, где надо на экран вывести переменные pwm и voltage

    #include
    #include
    #include
    #include

    void main(void)
    {
    pwm x=15;
    float voltage=0.15;

    GLCDINIT_t glcd_init_data;

    glcd_init_data.font=font5x7;
    glcd_init_data.readxmem=NULL;
    glcd_init_data.writexmem=NULL;
    glcd_init(&glcd_init_data);

    while (1)
    {
    glcd_outtextxyf(2,5,»PWM =»);

    glcd_outtextxyf(2,20,»Voltage =»);

    }
    }

  • посмотрите урок с ацп или с датчиком температуры

  • Уважаемый admin, я смотрел эти примеры, но все равно получаю ошибку 🙂 Давайте проанализируем, что не так, не хватает знаний чтобы самому понять.Теперь по порядку.
    CodeVisionAvr у меня версия 3.12. Подключаю дисплей на KS0108. Вот что генерит мастер.

    #include
    #include
    #include

    void main(void)
    {
    GLCDINIT_t glcd_init_data;
    // Graphic Display Controller initialization
    // The KS0108 connections are specified in the
    // Project|Configure|C Compiler|Libraries|Graphic Display menu:
    // DB0 — PORTD Bit 0
    // DB1 — PORTD Bit 1
    // DB2 — PORTD Bit 2
    // DB3 — PORTD Bit 3
    // DB4 — PORTD Bit 4
    // DB5 — PORTD Bit 5
    // DB6 — PORTD Bit 6
    // DB7 — PORTD Bit 7
    // E — PORTC Bit 0
    // RD /WR — PORTC Bit 1
    // RS — PORTC Bit 2
    // /RST — PORTC Bit 3
    // CS1 — PORTC Bit 4
    // CS2 — PORTC Bit 5

    /
    glcd_init_data.font=font5x7;
    glcd_init_data.readxmem=NULL;
    glcd_init_data.writexmem=NULL;
    glcd_init(&glcd_init_data);

    while (1)
    {
    // Place your code here

    }
    }

    Делаю по вашему примеру:
    char lcd_buf[10];
    void main(void)
    {
    char a = 0;
    while(1)
    {
    sprintf(lcd_buf,»a=%d», a);
    lcd_puts(lcd_buf);
    }

    Выдает ошибку Error: lcd3.c(165): undefined symbol ‘sprintf’
    Ага, не хватает библиотеки ввода/вывода, подключаем #include
    Ошибка исчезла, но появилась другая: Error: lcd3.c(167): undefined symbol ‘lcd_puts’
    Я так понимаю, что lcd_puts это было бы справедливо для библиотеки , а у нас

    Пока писал вам сообщение, удалось разобраться, копал саму библиотеку.
    Выводить надо так, glcd_outtextxy(40,5,lcd_buf), а не glcd_outtextxyf(40,5,lcd_buf) В первом случае:
    // Displays a NULL terminated character string located in RAM at the
    // specified x, y coordinates.
    void glcd_outtextxy(GLCDX_t x, GLCDY_t y, char *str);
    во втором
    // Displays a NULL terminated character string located in FLASH at the
    // specified x, y coordinates.
    void glcd_outtextxyf(GLCDX_t x, GLCDY_t y, flash char *str);
    RAM — хранит переменные, а flash константы
    RAM — можно менять, а flash — нет

  • вот видите как все просто, достаточно приложить минимум усилий и все получится

  • Здравствуйте! У меня такая проблема: пытаюсь на графический дисплей вывести буквы и цифры, но вместо этого получается такая крякозябра — http://imgur.com/yKAX7t4
    Так получается и с моими программами, и с программами-образцами, который идут с CodeVisionAVR. Собираю схему по инструкции, загружаю готовую программу но в Протеусе вылазит то же самое.
    В чем может быть проблема?

  • Какой то странный у вас дисплей по пинам

  • Какой был в Протеусе)
    Дисплей AGM1232G с SED1520, такой же задается и в CodeVision, с прямыми Е1, Е2 и инверсным RES. Вот кусок генерируемого подключения:
    Graphic Display Controller initialization
    The SED1520 connections are specified in the
    Project|Configure|C Compiler|Libraries|Graphic Display menu:
    DB0 — PORTA Bit 0
    DB1 — PORTA Bit 1
    DB2 — PORTA Bit 2
    DB3 — PORTA Bit 3
    DB4 — PORTA Bit 4
    DB5 — PORTA Bit 5
    DB6 — PORTA Bit 6
    DB7 — PORTA Bit 7
    A0 — PORTB Bit 0
    RD /WR — PORTB Bit 1
    E1 — PORTB Bit 2
    E2 — PORTB Bit 3
    RES — PORTB Bit 4

  • Попробуйте частоты разные у камня ставить.

  • В LCD Vision в полной версии можно загрузить готовый шрифт, любого размера и стиля который есть у вас в Windows включая русский, от маленького до огромного. LCD Vision сам с генерирует код, вам останется только назвать его и внести коррективы в созданные файлы по образцу хотя бы font5x7rus или штатного font5x7 коррективы вносятся в первых двух строках. Название шрифта нужно туда внести. Проверил все получается создавал от 5х7 до 24х44 можно и больше и использовать в проекте разные шрифты переключаясь между ними командой glcd_setfont(font24x44b);
    Изменения в файле «С» flash unsigned char font24x44b[]=
    Изменения в файле «h»
    #ifndef _FONT24X44B_INCLUDED_
    #define _FONT24X44B_INCLUDED_

    extern flash unsigned char font24x44b[];
    #pragma library font24x44b.c
    Где font24x44b название которое вы выбрали для шрифта.

  • Вопрос возможно не совсем по теме, но все же:
    Ответьте пожалуйста, у меня «затык» есть некая функция взятия значения из массива данных например:
    Draw_Simbol_LCD ( &Cyfra[‘!’]) или Draw_Simbol_LCD ( &Cyfra[33]) это не важно.
    Мне нужно как-то из нее «вытащить» значение 33 или ‘!’.
    То есть внутри этой функции написать что-то похожее на:
    void Draw_Simbol_LCD ( const uint16_t *sim)
    {
    uint8_t y;
    y=sim; // Что-бы «y» равнялся ‘!’ или значению 33
    }
    Как сделать что-бы «Y» у меня равнялся значению в скобках &Cyfra[33], то есть 33? Большое спасибо.

  • не очень понял вопрос, но в общем то как у вас написано так и должно работать. только вы берете 2байтную переменную, а пихаете ее в однобайтную, поэтому старший байт отбросится

  • Андрей, я вообще не пойму что у вас за запись такая &cyfra[33] если имя массива это и есть адрес. Где вы это взяли? судя по названию массива сами писали. И вам трудно будет обяснить)

  • Писал конечно сам, выход нашел. Может не совсем корректно объяснил, попробую еще раз есть массив «cyfra» представлен в форме записи &Cyfra[‘!’] возвращается число например 0х08 не важно, но мне еще нужно чтобы внутри функции можно было использовать помимо значения из массива еще значение ‘!’ то есть 33. Выкрутился так:
    Draw_Simbol_LCD(Cyfra,’!’); или по другому Draw_Simbol_LCD(&Cyfra[0],’!’);
    А задача состоит в следующем, поскольку перепробовал все примеры из CVAVR (даже купил лицензию, и написал в службу поддержки) с цветными дисплеями запустить не удалось ни один из примеров входящих в состав CVAVR , решил написать свой алгоритм. После успешной инициализации одного из дисплеев, встал вопрос со шрифтами и соответственно их реализации в проекте после генерации с помощью LCD Vision. Изучив внимательно с генерированный код я понял алгоритм его создания, хочу сразу сказать алгоритм генерации действует через большую ж…. то есть с точностью до наоборот чем например BitFontCreator в итоге я написал функцию вывода символа на цветной TFT экран дисплея на основе с генерированного кода. Выглядит «страшно», но работает проверил со всеми стилями с генерированного шрифта. Проверил правда на Atmel Studio код ниже:
    void Draw_Simbol_LCD ( uint16_t x, uint16_t y, uint16_t color,uint16_t phone,const uint16_t *sim, uint8_t n)
    {
    int8_t z;
    uint8_t j,i;//переменные координат, размерности по строкам и столбцам
    uint16_t sum=0,k=0;

    uint8_t h,per,kol,nom,w,ob;
    /*
    h — высота символа
    per- порядковый номер первого символа, обычно «32»
    kol- количество символов в массиве
    nom- номер символа в массиве » » это №1 «!» это №2 и т. д.
    w — ширина символа в массиве
    ob — переменная цикла для расчета расположения кода символа в массиве
    sum- точное местоположение начала кода в символа в массиве
    */

    h=pgm_read_byte(&sim[0]); //Высота символа
    per=pgm_read_byte(&sim[1]);//Порядковый номер первого символа
    kol=pgm_read_byte(&sim[2]);//Количество символов в массиве
    nom=n-per;
    w=pgm_read_byte(&sim[nom+3]);//Расчет значения ширины символа
    for(ob=0;ob0)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=9)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=17)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=25)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=33)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=41)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=49)sum++;
    if((pgm_read_byte(&sim[ob+3]))>=57)sum++;

    }

    sum=sum*h+kol+3;

    for( j=0; j<h; j++)//для строк по x (Высота)
    {

    Set_Cursor(x+j, y);//установка курсора в заданную координату
    z=0;
    for( i=0; i> (z + i)))
    {
    LCD_Write_Data(color);
    }
    //если в массиве символа 0 — пишем точку цвета фона size раз
    else
    {
    LCD_Write_Data(phone);
    }
    }
    }

    }
    Сама функция выгладит так:
    Draw_Simbol_LCD(100,100,RED,BLUE,Cyfra,’z’); Если кому то интересно могу выложить весь проект, если конечно админ позволит.

  • Извините часть кода обрезается не знаю почему. По этому функция напечаталась наполовину.

  • Андрей, можете вылаживать, что сдесь такого. Но еще раз спрашиваю что за запись &sim[]? что это за взятия адреса в масива? где вы видели это ?

  • Запись &sim[0] это взятие нулевого по счету значения из массива его переменной sim (можете назвать как хотите) фактическое название массива Cyfra. Соответственно &sim[1] это первое значение &sim[2] второе и т. д. Посмотрите файл «Прочти», в ссылке на проект с моего яндекс диска. Также там ссылка на сайт с примером и подробным описанием всех функций, так же с примерами. Хочу так же сказать инициализация в примерах временно у меня со шрифтами, и на сайте «Кривая». Нормальная инициализация и настройка дисплея в примере вывода картинки из SD карты на дисплей, это я уже переделал как положено, ссылку на проект с примером и библиотеками так же выкладываю ниже в комментарии. Потому что админ проверяет ссылки прежде чем выложить на сайте. Если возникнут вопросы или хотите получить уже законченный проек со шрифтами пишите мне на мой емаил узнаете его название как зайдете на яндекс диск. Ссылку на проект с использованием sd карты я уже выкладывал относительно недавно и она осталась. Ищите в моих комментариях по графическому дисплею в уроках №18 не помню смотрите во всех трех. Проект с использованием SD карты можно посмотреть в протеусе после установки в не го всех необходимых библиотек. Все библиотеки и использованные программы находятся в архиве в свободном доступе. Если что забыл, то пишите.

  • Ссылка на проект со шрифтами https://yadi.sk/d/J2Hp5GzlraA9a (еще «сырой»)
    Ссылка на проект с SD картой https://yadi.sk/d/sXAVXtp6raA9S (полностью рабочий с библиотеками)

  • Dimamima, запись типа &arr[n] возвращает адрес н-го элемента массива arr. Аналогично (arr + n), но можно и так))

  • Андрей, имя массива это и есть адрес. Я просто хочу узнать где вы такую форму записи видели? вы просто не понимаете как в си или си++ все работает. Форма записи & sim[n] i sim[n] это одно и тоже. даже можна как ether написал sim+n; Просто интересно, вы на сайтах или в учебниках такой формат видели?

  • Для Dimamima. На сайте. Админ разрешит комментарий который я выложил, там в документации адрес сайта. Вообще-то, я не претендую на роль знатока СИ и отношу себя к начинающим.

  • Dimamima, а вот тут Вы не правы…. &sim[n] и sim[n] — это далеко не одно и то же. Первое — взятие адреса н-го элемента массива сим, а второе — это прямой доступ к этому элементу. Если оч. детально рассматривать — то квадратные скобки — это оператор получения доступа к элементу массива. И он выполняется первым, до оператора &. И в записи &сим[н] — сначала вы получаете доступ к н-му элементу массива сим, а потом «добываете» его адрес. А сим[н] — просто получаете доступ к н-му элементу.
    Пересмотрите тему Указатели и массивы в том же К&Р 🙂

  • ether, ви пишете бредятину ! Компилятор все сводит к одному *(sim+n). напишете ви sim[n] или sim +1 все сводиться к одному. Но если вы напишете sim и &sim то это уже совсем разные данние будут.

  • Dimamima, что-то агрессией и спором тут попахивает) Спорить не хочу, просто откройте Керниган и Риччи, глава — указатели и массивы. Посмотрите. И все)

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика