Вторник, 23.04.2024, 18:25
| RSS
[SEARCH_TITLE]
[SEARCH_FORM]
Важно!!!
Для успешного просмотра
сайта воспользуйтесь
браузером Mozilla Firefox



Мини-Профиль
Гость


Группа:
Гости
Время:18:25

Гость, мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизуйтесь!

Категории раздела
О программаторах [4]
Не много о том как и с помощью чего программировать.
Программирование в BascomAVR [6]
Учимся благодаря статьям писать программы. Язык Basic
Программирование в CV AVR? [4]
Учимся благодаря статьям писать программы. Язык Си

Поиск

Наш опрос
Какой язык вы хотели бы изучать?
Всего ответов: 352

Друзья сайта
roboforum
  • robozone
  • Железный феликс
  • robo.com.ua
  • imobot
  • ASARobotics
  • Grover
  • Электроника
  • Your Device
  • Программирование BASCOM
  • Basic для PIC мк
  • Электроника для всех
  • RassionRobots
  • Newrobots-world

  • Статистика

    Каталог-Молдова - Ranker, Statistics
    RoboRing.Ru
    << | list | ? | >>
    Rambler's Top100
    Рейтинг@Mail.ru
    Рейтинг робо-сайтов


    Помоги сайту
    ЯндексЯндекс. ДеньгиХочу такую же кнопку


    Главная » Статьи » Программирование » Программирование в CV AVR?

    Подключение LCD модуля к ATmega8.

    Вдруг и неожиданно потребовалось видеть определенные данные, которые храняться и меняются во время работы микроконтроллера ATmega8.

    Как это осуществить? Я знаю три пути: 1. Запустить программу в отладчике; 2. МК будет записывать значения переменных в память, затем

    программатором их считывать; 3. Выводить значения на экран - LCD.


    Способ № 1: Самый замечательный и удобный, но теория зачастую отличается от практики - работающая на отладчике/эмуляторе программа,

    может давать сбой при запуске на МК.


    Способ № 2
    : Ну это совсем не хорошо. Как то коряво. ради одной переменной столько трудностей... - это жуть.


    Способ № 3: Как видно из названия статьи, именно этот способ мне и пригленулся - да и на будущее пригодится.


    И не обращаясь к теории и томам информации, как надо было сделать, я направился в магазин. И как озарение, лежит на витрине WH1602D!!! Такой красивый и привлекательный модуль. На радостях я отсчитал 200 рублей и получил на руки пакетик из "пузырчатой" пленки с надписью "WH1602D". Как попал домой помню с трудом. :)


    Уже дома, при помощи компьютера и интернет, я узнал, что WH1602D - это LCD модуль, имеет 2 строки по 16 символов в каждой + наличие русского алфавита. О великое счастье, на угад купил замечательную штуку.


    Радость закончилась, когда я начал вникать, как это чудо подключить к МК и заставить написать что-либо.


    Первым делом, качаем даташит! /Stati/LCD/WH1602D-YGB-CP.pdf Читаем (на сколько позволяют знания английского языка), и не фига не понятно.

    Вторым делом, поиск по различным форумам - уже лучше - ясно, что подключается эта радость по стандартному для подобных экрашек принципу. Как подключить именно модель WH1602D не нашел :( Выход один, найти описание подключения подобного экрана и изучить принцип.

    Ищем... Ищем... И находим статью: серия "Микроконтроллеры? Это же просто!", название: "Глава 4. Сопряжение микроконтроллера с индикаторами различных типов" - к сожаления я не знаю откуда эта статья. /Stati/LCD/manual1.pdf


    Читаем... И еще разок... Вот, уже могу выделить особо важные моменты...

    Открываем даташит на наш модуль, сравниваем... корректируем... Результат !!!

    Теория получена. подключаем, пишем прогу, тест... далее потом расскажу.


    И так, результат (теория):


    LCD модуль WH1602D иммет 14+2 контактов = 16.

    +2 - это подсветка дисплея, на модуле обозначаются как "А" и "К" - анод и катод соответственно - тут все ясно, подоем питание (5 вольт) и

    радуемся свечению панельки.

    14 контактов:

    3 из них служат для подключения питания:

    1. Vdd - + 5 вольт. - Питание модуля.

    2. Vss - Земля ( - ). - Питание модуля.

    3. V0 - контрастность изображения. - Если закоротить на минус, то мы получим максимальную контрастность (все точечки будут светиться на всю, и мы не чего не увидим. Необходимо этот контакт подключить к минусу через переменный резистор номиналом 10 кОм. Мне понравился контраст при примерно 4 кОм.


    Еще 3 контакта управляющие:

    4. RS - коммандный флаг - если подать 0, то мы посылаем команду. Если 1, значит посылаются данные.

    5. R/W - Чтение/запись - 1 - читаем данные, 0 - записываем.

    6. E - импульс - что-бы модуль начал обработку данных с остальных контактов, необходимо установить 1 на некоторое время.


    Остальные 8 контактов служат носителями данных. называются DB0 - DB7.

    Смысл такой. Чтобы заставить модуль, что-то сделать необходимо установить логические нули и/или еденички на пинах RS, R/W и DB0 - DB7.

    После этого подать импульс на пин E. Выждать время и можно посылать новые команды.

    Открываем даташит, распечатываем табличку: "11.Instruction Table" и вешаем ее на стенку, чтоб перед глазами была.

    Все просто, устанавливаем нужные пины в нужное состояние в соответствии с табличкой и подаем импульс. В таблице указаны странные сочетания букв, вместо них надо поставить 0 или 1 – как нам надо. Рассмотрим команды и эти знаки поближе:

    Clear Display – Полностью очищает память и устанавливает курсор в позицию 0, т.е. экран чистенький и вывод символов начнется сначала.


    Return Home – Устанавливает курсор в позицию 0, не очищая памяти. Экран не очищается (показывает, что и было), но вывод символов начнется сначала.


    Entry Mode Set – Авто передвижение курсора и экрана за ним. Тут поподробнее, ибо важно! Команда использует два указателя: I/D и SH.

    Если I/D = 0, то после вывода символа на экран курсор останется на месте и следующий символ заменит его.

    I/D = 1, после вывода символа курсор автоматически переместится на следующую позицию.

    SH – Памяти у модуля намного больше, чем на один экран знаков. Т.е. можно всю память загрузить стихом Пушкина, и лишь смещая позицию экрана относительно памяти показывать две произвольных строки стиха. И так.

    SH = 1 – экран будет смещаться за курсором (внимательно! Если I/D = 1 и SH = 1,то посылая знак на экран в позицию = 0, то мы его не увидим, т.к. Позиция курсора после ввода символа стала =1, экран сместился на его положение и отображает данные начиная с позиции 1, а знак мы записали в 0).

    SH = 0 – запрещаем смещать экран относительно памяти. В общих случаях я рекомендую использовать настройку : I/D = 1; SH = 0 – удобно, что курсор смещается сам, а экран стоит на месте и когда надо мы его сами переставим. Но это общие случаи и возможно кому-то режим авто смещения экрана будет полезен.


    Display ON/OFF Control – Управление включением/выключением экрана и курсора. Используется три указателя: D, C, B.

    D – Вк/Вык экран, тут все понятно, т.е. можно работать с памятью модуля, а на экране будет чисто. D = 0 – Экран выключен. D = 1 – Экран включен.

    С - Вк/Вык отображение курсора. С = 0 – курсор не отображается, С = 1 – на экране на месте курсора будет высвечиваться черточка (удобно, когда пользователь что-то вводит).

    B - Вк/Вык мерцания курсора. B = 0 – курсор отображается постоянно. B = 1 – курсор моргает с небольшой частотой как в консольках. Симпатично смотрится. :)


    Cursor Or Display Shift – что-то типа Entry Mode Set, если честно, то я так и не понял, что это за команда. Если кто знает, то сообщите мне или напишите в комментариях.


    Function Set – Установка режимов работы модуля. 3 ключа DL, N, F

    DL – модуль может работать с шиной 8 бит или 4 бит, 8 бит – быстрее (используем все пины), 4 бита – экономия на портах МК (используются пины DB4-DB7). Я работал только с 8 битами, так проще для понимания. И так, DL = 1 – это 8 бит, DL = 0 – это 4 бита.

    N – количество рабочих строк модуля. N=1 – это 2 строки. N=0 – это 1 строка.

    F – модуль может отображать символа размером 5х11 точек или 5х8 точек. F=0 – это 5х8, F=1 – 5х11.


    Set CGRAM Address – Установить курсорчик в ячейку памяти знакогенератора. Можно рисовать собственные символы в памяти модуля, как это делать я еще не знаю (пока не потребовалось). Используя ключи AC0-AC5, указываем ячейку памяти, и курсорчик в нее установится. AC0-AC5 – в совокупности представляют собой шестиразрядное двубитное число – это и есть адрес ячейки памяти.


    Set DDRAM AddressУстановить курсор в ячейку видео памяти. Силой заставляем поставить курсор в указанную ключами AC0-AC6 ячейку видео памяти. Именно в этой ячейке отобразится знак, который будет послан следующим. AC0-AC6 – в совокупности представляют собой семиразрядное двубитное число – это и есть адрес ячейки памяти.


    Read
    Busy Flag and Address - Очень интересная и полезная команда. Busy Flag (BF) – это флаг занятости модуля. Когда модуль занят, по после посылки этой команды, мы увидим 0 на ножке DB7.


    Write Data to RAM – записать данные в модуль. Самая часто-используемая команда. Установили курсор куда нам надо (либо командой Set DDRAM Address, либо авто-сдвигом, ключ I/D), и записываем номер знака. Ключи D0-D7 – это восьмиразрядное двубитное число, которое и несет в себе номер знака.


    Read Data from RAM – считать из памяти номер знака, по адресу, указанному ключами D0-D7. – Я еще не пользовался этой командой, так что не в курсе ее работы. :(


    Это все команды модуля. Их очень мало, но достаточно для работы.


    Ах да !!! В памяти модуля хранится таблица символов. В даташите она называется «10.Character Generator ROM Pattern». Находим нужный знак, по подписям в начеле столбцов и строк получаем его номер и посылаем командой Write Data to RAM.

    К примеру, знак «G» : столбец – 0100, строка – 0111 отсюда номер символа в памяти модуля = 01000111.


    Все понятно? Да! Те, кто уже пробует писать программу и подключать модуль уже обломались. Так сразу модуль не заработает!!! Необходимо его сначала инициализировать. Что означает это жуткое слово? – Мы должны сказать модулю: «Включайся… Работай… Работай с 2 строками… Включи экран…» и т.д. Одним словом настроить прибор для работы. В даташите есть два алгоритма инициализации модуля, один для 8 бит, второй для 4 бит. Т.к. я работаю в 8 битном режиме, то и разбирать буду именно его.


    Но для начала подключим модуль к микроконтроллеру. Я использовал МК ATmega8 (Другова нет). Необходимо припаять 14 проводочков к модулю, можно и штекер какой-нибудь использовать, лучше сразу в магазине купить.

    Питание и контраст подключаем к питанию всей схемы остальные пины куда попало :), в том смысле, что к любым свободным портам микроконтроллера. Я использовал порт D для данных (пины модуля DB0-DB7), эти пины у меня не занимаются прочими функциями МК и очень удобно в дальнейшей работе – данные записываются сразу в один порт без заморочек.

    Под 3 управляющих пина я использовал порт С, его первые три пина.


    И так, получилось вот что:

    PORTС

    PС0 – E – импульс.

    PC1 – RS – команда или данные.

    PC2 – R/W – чтение или запись.

    PORTD

    PD0 – DB0 – данные байт 0

    PD1 – DB1 – данные байт 1

    PD2 – DB2 – данные байт 2

    PD3 – DB3 – данные байт 3

    PD4 – DB4 – данные байт 4

    PD5 – DB5 – данные байт 5

    PD6 – DB6 – данные байт 6

    PD7 – DB7данные байт 7


    Подключил все как надо. Теперь дело за программой.

    Для удобства я все делал функциями, чтобы в будущем собрать все в файл для Include().



    void Clear_ports(void) // Функция устанавливает 0 на всех пинах.

    {

    PORTD=0b00000000;

    PORTC=0b0000000;

    }

    void Init_ports(void) // Указываем необходимые порты как выходы

    {

    DDRD=0b11111111;

    DDRC=0b0000111;

    Clear_ports(); // сразу очищаем все порты.

    }



    Для настройки МК все готово, теперь необходимо инициализировать модуль.

    Понадобится вспомогательная функция, которая будет посылать импульс готовности модулю. Это всего три строки, но каждый раз их писать нудно:


    void Impuls(void) // импульс готовности

    {

    PORTC |= _BV(PC0); // на пин E устанавливаем логическую единичку.

    _delay_ms(1); // немного подождем

    PORTC &= ~_BV(PC0); //Убираем сигнал

    }



    Задержка в 1 мс даже великовата, в даташите это время намного меньше, но задержку в 1мс незаметно, зато я уверен, что команда точно прошла.


    Вот и функция инициализации модуля, сделана точно по алгоритму из даташита. Одно замечание в алгоритме даташита не указано, что после каждой команды (пункта) необходимо посылать импульс, в программе импульсы хорошо видно.


    void Init_LCD(void) // функция инициализации модуля.

    {

    _delay_ms(20); // после подачи питания на модуль надо подождать.

    PORTD=0b00110000; // Команда «РАБОТАТЬ !!!»

    PORTC=0b0000000;

    Impuls(); // Посылаем бит готовности (импульс Е)

    _delay_ms(5); // ждем, пока модуль врубится…

    PORTD=0b00110000; // Команда «Ты чё не понял??? РАБОТАТЬ !!!»

    PORTC=0b0000000;

    Impuls();

    _delay_us(100); // уже быстрее доходит…

    PORTD=0b00110000; // «Работать!!! А не то разобью об стену !!!»

    PORTC=0b0000000;

    Impuls();

    //даже думать не пришлось, все как у людей – пока не стукнешь…

    PORTD=0b00111100; // 8 bit, 2 line, 5*11 (команда Function Set)

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00001100; //display ON OFF

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00000001;//Clear all

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00000110; //Entry mode set

    PORTC=0b0000000;

    Impuls();

    }



    Ну вот и запустили. В командах можно сразу выставлять нужные настройки. Все команды кроме Function Set можно использовать в работе программы. Команда Function Set вызывается один раз при инициализации.

    Ура-ура! Инициализация есть!!! Теперь функция записи знака в память модуль для его вывода на экран. Т.к. я использую режим авто сдвига курсора, то запись в память осуществляется лишь одной командой Write Data to RAM .




    void Char_To_LCD ( char TXT ) // записать знак в память модуля

    {

    PORTD=TXT; //в порт записываем номер знака в таблице

    PORTC |= _BV(PC1); // устанавливаем ключ RS.

    Impuls();// Посылаем бит готовности (импульс Е)

    }



    Теперь соберем все в кучу и напишем основную функцию программы (mail):




    #include

    #include

    #include

    void Clear_ports(void)

    {

    PORTD=0b00000000;

    PORTC=0b0000000;

    }

    void Init_ports(void)

    {

    DDRD=0b11111111;

    DDRC=0b0000111;

    Clear_ports();

    }

    void Impuls(void)

    {

    PORTC |= _BV(PC0);

    _delay_ms(1);

    PORTC &= ~_BV(PC0);

    }

    void Init_LCD(void)

    {

    _delay_ms(20);

    PORTD=0b00110000;

    PORTC=0b0000000;

    Impuls();

    _delay_ms(5);

    PORTD=0b00110000;

    PORTC=0b0000000;

    Impuls();

    _delay_us(100);

    PORTD=0b00110000;

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00111100; // 8 bit, 2 line, 5*11

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00001100; //display ON OFF

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00000001;//Clear all

    PORTC=0b0000000;

    Impuls();

    PORTD=0b00000110; //Entry mode set

    PORTC=0b0000000;

    Impuls();

    }

    void Char_To_LCD ( char TXT )

    {

    PORTD=TXT; //*

    PORTC |= _BV(PC1);

    Impuls();

    }

    // ------- Основная программа ---------

    void main(void)

    {

    Init_ports(); // настраиваем МК

    Init_LCD(); // инициализация модуля

    Char_To_LCD(0b10101000); // П

    Char_To_LCD(0b01110000); // р

    Char_To_LCD(0b10111000); // и

    Char_To_LCD(0b10110011); // в

    Char_To_LCD(0b01100101); // е

    Char_To_LCD(0b10111111); // т

    Char_To_LCD(0b00100001); // !

    while(1) { // Бесконечный цикл

    }

    }



    Вот и все! Если все сделано правильно, то на экране появится надпись «Привет!».

    Ошибки, которые совершал я при первых пробах:

    1. Функцию инициализации пока не трогайте. Сначала запустите как есть и убедитесь, что «Привет!» появился. Настройки так 100% рабочие – проверял.
    2. Контраст модуля. Пин V0 – если он упал на (-), то все засвечено и знаков не видать. Если он не подключен, то экран будет пустой, без каких-либо точек. Лучше поставьте переменный резистор и покрутите.
    3. Временные задержки. Во всей программе от посыла импульса и до инициализации используются задержки по времени. В даташите указано их минимальное значение. Но написано «не менее», отсюда смело ставим немного больше на всякий случай. Первые запуски я проводил с задержками в 10 мс везде – буквы выводились по одной и медленно, но 100% работало. Уже потом я их снижал для ускорения работы.
    4. Повнимательнее с настройками авто смещения курсора и экрана относительно памяти.


    Ну вот и всё. Все остальное изучайте сами. Я долго бился, чтобы узнать, написанное выше и поделился с вами. К примеру, таблицу символов и их номера можно прошить в память МК, это сильно упростит жизнь – можно будет написать функцию, которая будет посылать сразу строки – конечно по одному символу, но программист будет писать строками. Короче, делайте что хотите!



    Источник: http://groversuper.ucoz.ru/publ/2-1-0-2
    Категория: Программирование в CV AVR? | Добавил: Space (28.04.2008) | Автор: Grover
    Просмотров: 25292 | Теги: дисплей, ЖК, вывод информации на жк, LCD, CV avr дисплей | Рейтинг: 4.7/15 |
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]