Понедельник, 02.12.2024, 02:19
| RSS
[SEARCH_TITLE]
[SEARCH_FORM]
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Архив - только для чтения
Подключение LCD модуля к ATmega8.
GroverДата: Среда, 27.02.2008, 13:09 | Сообщение # 1








Зарегистрирован 04.02.2008
Группа: Опытные
Сообщений: 130
Город: Воронеж
Статус: Offline
Вдруг и неожиданно потребовалось видеть определенные данные, которые храняться и меняются во время работы микроконтроллера ATmega8.

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

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

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

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

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

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

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

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

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

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

Читаем... И еще разок... Вот, уже могу выделить особо важные моменты...
Открываем даташит на наш модуль, сравниваем... корректируем... Результат !!!
Теория получена. подключаем, пишем прогу, тест... далее потом расскажу.

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

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 – курсор моргает с небольшой частотой как в консольках. Симпатично смотрится. smile

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. – Я еще не пользовался этой командой, так что не в курсе ее работы. sad

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

Ах да !!! В памяти модуля хранится таблица символов. В даташите она называется «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().

Code

void Clear_ports(void) // Функция устанавливает 0 на всех пинах.
{
PORTD=0b00000000;
PORTC=0b0000000;
}

void Init_ports(void) // Указываем необходимые порты как выходы
{
DDRD=0b11111111;
DDRC=0b0000111;
Clear_ports(); // сразу очищаем все порты.
}

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

Code

void Impuls(void) // импульс готовности
{
PORTC |= _BV(PC0); // на пин E устанавливаем логическую единичку.
_delay_ms(1); // немного подождем
PORTC &= ~_BV(PC0); //Убираем сигнал
}

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

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

Code

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 .

Code

void Char_To_LCD ( char TXT ) // записать знак в память модуля
{
PORTD=TXT; //в порт записываем номер знака в таблице
PORTC |= _BV(PC1); // устанавливаем ключ RS.
Impuls();// Посылаем бит готовности (импульс Е)
}

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

Code

#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. Повнимательнее с настройками авто смещения курсора и экрана относительно памяти.

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

Добавлено (27.02.2008, 13:09)
---------------------------------------------
оригинал статьи:
http://groversuper.ucoz.ru/publ/2-1-0-2

Прикрепления: 2512594.jpg (41.6 Kb) · WH1602D-YGB-CP.pdf (243.6 Kb) · manual1.pdf (929.4 Kb)


--------
GroverSuper.ucoz.net - мои странички.


Сообщение отредактировал Grover - Среда, 27.02.2008, 12:17
 
SpaceДата: Пятница, 28.03.2008, 15:24 | Сообщение # 2








Зарегистрирован 25.12.2007
Группа: Администраторы
Сообщений: 1103
Статус: Offline
http://startcd.narod.ru/lcd_clock2/lcd_clock.html - Часы, AtMega16 и LCD дисплей.
Исходник, прошивка и проект для протеуса
 
  • Страница 1 из 1
  • 1
Поиск: