AVR Урок 12. LCD индикатор 16×2. Часть 4



 

Урок 12

Часть 4

 

LCD индикатор 16×2

 

Сегодня мы продолжим изучение жидкокристаллического индикатора символьного, который способен выводить определённые символы в две строки по 16 символов в каждую.

Вернёмся в проект Atmel Studio.

В прошлой части мы завершили инициализацию дисплея.

Теперь хотелось бы что-нибудь увидеть на дисплее. Для этого нам нужна будет ещё одна функция, которая будет передавать только данные, а не команду

 

//—————————————-

void sendchar(unsigned char c)

{

sendbyte(c,1);

}

//—————————————-

 

В данной функции мы просто вызываем другую с единичкой, чтобы каждый раз не писать единички. Данную функцию мы напишем после функции sendbyte.

Ну и давайте попробуем в дисплей передать пару каких-нибудь символов в функции main()

 

LCD_ini(); //Инициализируем дисплей

sendchar('n');

sendchar('m');

while(1)

 

Соберём код и запустим проект в протеусе.

 

 

Всё работает и мы видим следующую картину. В видеоуроке была ошибка, но потом она была исправлена, хотя я думал, что не было изображения из-за того, что не написана была функция позиционирования. Вот так работает дисплей

 

image20

 

Собственно, теперь давайте всё-таки напишем функцию позиционирования, чтобы мы могли выводить символы не только подряд, но и в любое место диспелея. Назовём ее setpos. Вообще данная функция будет устанавливать указатель в определенное место DDRAM. Выше была показана таблица организации данной памяти и соответствия её ячеек определённым знакоместам на дисплее. Будем этого и придерживаться при написании кода. Напишем нашу функцию после функции sendchar

 

//—————————————-

void setpos(unsigned char x, unsigned y)

{

}

//—————————————-

 

Ну, соответственно, у функции будет два входных аргумента — позиция по горизонтали и позиция по вертикали.

Добавим переменную типа char и вычислим её значение в зависимости от значений x и y. Значения входных аргументов мы будем начинать от нуля, а не от единицы. Поэтому чтобы вычислить адрес по y в памяти DDRAM, нам достаточно умножить значение y на 0x40, так как именно с данного адреса начинается 2 строка, а у нас она будет выглядеть как 1. Затем прибавляем x, тем самым получим смещение по горизонтали в данной памяти. И ещё по операции «ИЛИ» вычисленное значение мы сложим с двоичным числом 0b10000000, так как команда передачи адреса памяти DDRAM выглядит вот так

 

image21

 

То есть в 6 бите мы передаём единицу для того, чтобы контроллер дисплея «понял» что мы даём именно такую команду — передача адреса памяти DDRAM, чтобы контроллер дисплея установил указатель именно туда, какую позицию мы даём ему в оставшихся семи младших битах — DB6-DB0.

 

 

Вот такой мы получим код функции

 

void setpos(unsigned char x, unsigned y)

{

  char adress;

  adress=(0x40*y+x)|0b10000000;

  sendbyte(adress, 0);

}

 

Ну и давайте теперь вызовем данную функцию в функции main для порядка, установив жёстко перед вызовом фунции вывода символа указатель памяти на нулевой адрес

 

LCD_ini(); //Инициализируем дисплей

setpos(0,0);

sendchar('n');

 

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

 

sendchar('m');

setpos(8,0);

sendchar('x');

sendchar('f');

 

После сборки и запуска мы должны увидеть вот такой результат

 

image22

 

Также давайте что-нибудь выведем на другую строку дисплея

 

sendchar('f');

setpos(8,1);

sendchar('r');

sendchar('e');

 

А вот и результат

 

image23

 

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

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

 

 

Предыдущая часть Программирование МК AVR Следующая часть

 

Техническая документация на дисплей

Техническая документация на контроллер дисплея HD44780

 

Программатор и дисплей можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Дисплей LCD 16×2

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

AVR LCD индикатор 16×2

17 комментариев на “AVR Урок 12. LCD индикатор 16×2. Часть 4
  1. Riverman:

    Владимир, подскажите как вывести на LCD значение переменной ,

    например

    unsigned char Time_mode;

    • Евгений:

      char не бывает signed, или я совсем ничего не понимаю в форматах.

      Если переменная один символ:

      char Time_mode;

      то вывод на экран будет  выглядеть так:

      sendchar(Time_mode);

      • Евгений:

        Да, про char в общем случае, я наврал. Бывает и unsigned char, и signed char, и просто char. Зависит от реализации. Так как давно работаю с реализацией char'а как unsigned, то и в голове между ними стоял знак равенства.

      • Alex:

        Тип Размер в байтах (битах) Интервал изменения
        char 1 (8) от -128 до 127
        unsigned char 1 (8) от 0 до 255

  2. Михаил:

    В протеусе все замечательно, но у меня на реальном дисплее все, что не занято выводимыми символами было забито нулями или знаками курсора.

    Потом дошло, что не хватает очистки экрана. Добавил в инициализацию: 

    sendbyte(0b00000001, 0); // очистка дисплея
    _delay_ms(1);

    Хотя, наверное, правильнее сделать в виде функции и вызывать по мере надобности.

  3. Алексей:

    Как передать значения переменной
    unsigned char menu_tar=1;
    if(menu_tar==1){setpos(0,0); str_lcd(«Menu PWM:»); sendbyte(menu_tar, 1);}
    if(menu_tar==1){setpos(0,0); str_lcd(«Menu PWM:»); str_lcd(menu_tar);} Думал так должно работать. Но тоже не то. Ну очень нужно. Всю голову сломал.

  4. REQW:

    В очередной раз Спасибо за уроки! Все расписано максимально подробно.
    Но опять появился вопрос:
    Объясните каким образом символ n «превращается» в 1 байт в виде единиц и нулей??? Т.е. мы передаем в sendbyte символ n, а по идее должны передать однобайтное (0 — 255). Как?
    А так же, объясните значение одинарных кавычек (»).

    Спасибо!

  5. ежовая_рукавица:

    Не совсем понял, как работает setpos().
    По сути, эта функция выдает sendbyte(adress, 0), где adress некоторым образом вычисляемая величина(ктати,исходя из чего она так вычисляется?), а 0 это состояние шины rs(команда).
    Как она заставляет перепрыгивать курсор на вторую строку?
    //———————————————————
    Пока писал все это, решил заглянуть в даташит.
    Там это описано, но «поймут не только лишь все» :-D, а только те, хорошо знаком с английским языком.

    Cursor or display shift shifts the cursor position or display to the right or left without writing or readingdisplay data (Table 7). This function is used to correct or search the display. In a 2-line display, the cursormoves to the second line when it passes the 40th digit of the first line. Note that the first and second linedisplays will shift at the same time.When the displayed data is shifted repeatedly each line moves only horizontally. The second line displaydoes not shift into the first line position.The address counter (AC) contents will not change if the only action performed is a display shift.

    «Нельзя вполне понять «Капитал» Маркса, и особенно его I главы, не проштудировав и не поняв всей Логики Гегеля»
    Неустранимый принцип)

  6. здравствуйте. не могу понять, почему ни в протеусе ни на реальном дисплее код не работает(ничего не выводится)? пробовал с вашим исходником, тоже ничего не происходит. компилятор ошибок не выводит. пробовал разные контроллеры(мега328, мега8), менял частоту во фьюзах.

    • Сергей:

      Anton , такая же фигня пробовал этот проект на атмеге 328 не один символ не отображается , в чём может быть проблема ?

  7. Сергей:

    Создал проект для меги328Р, всё выводится, но вот проблема — всё, что не символы — черные квадраты. Приходится подставлять пробелы… Также воспользовался калькулятором русского языка в символы, теперь дисплей с алиэкспресс выводит и русские символы.
    Помогите победить черные квадратики в отсутствущих символах (очистку дисплея перед выводом подставлял)

  8. uuu000:

    Цикл while пустой поэтому нужно писать фигурные скобки,иначе пишет ошибку
    while(1)
    {};

  9. Сергей:

    void sendbyte(unsigned char c, unsigned char mode)
    {
    if(mode==0) rs0;
    else rs1;
    unsigned char hc=0;
    hc =c>>4;
    sendhalfbyte(hc);sendhalfbyte(c);
    }
    скажите пожалуйста мочему ругается программа на строчку else rs1; при компиляции скеча, прошу сильно не пинать я только учусь . зарание всем спасибо )

  10. Oleg:

    Снимите урок про вывод текста на графический дисплей 12864b v2.0 ST7920

    • К сожалению, у меня такого дисплея нет, но если вдруг появится, постараюсь с ним разобраться и обязательно сниму урок, конечно не факт, что именно с этим контроллером (имею в виду AVR).

  11. sarvsn:

    Благодарю автора за труд и стремление поделиться своими знаниями с новичками.

    —————-

    Как у многих, у меня была ошибка function argument #1 of type 'flash unsigned char [13]' is incompatible with required parameter of type 'unsigned char []' .

    Решил её добавлением слова flash в объявлении типа данных для аргумента функции str_lcd

    // —————————— //

    void str_lcd (char flash str1[])
    {
    char n;
    for(n=0;str1[n]!='\0';n++)
    sendchar(str1[n]);
    }

  12. Anton:

    «То есть в 6 бите мы передаём единицу для того, чтобы контроллер дисплея «понял» что мы даём именно такую команду»

    У вас опечатка, не 6, а 7 бит

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

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

*