AVR. Учебный курс. Подключение к AVR LCD дисплея HD44780

Сегодня разменял четверть века
Сегодня разменял четверть века!
Так случилось, что прикупил я тут себе поприколу LCD дисплейчик две строки по восемь символов. Валялся он в ящике валялся, да чегото поперло меня и решил я его заюзать, попутно вкурив в его работу. О том как подключить к AVR LCD дисплей я вам сейчас и поведаю.

Для начала оговорюсь сразу, что речь тут пойдет о LCD индикаторах на контроллере HD44780, который стал промышленным стандартом де-факто на рынке цифро-буквенных дисплеев. Продается везде где только можно, стоит недорого (8х2 мне обошелся порядка 150 рублей), а также под него написана куча кода. Я же, как обычно, решил изобрести велосипед и сварганить свою собственную тру-библиотеку для работы с этим типом индикаторов. Разумеется на ассемблере, а на чем же еще? ;)

Подключение.
LCD на базе HD44780 подключается к AVR микроконтроллеру напрямую к портам. Есть два способа подключения — на 8 бит и на 4 бита. В восьмибитном режиме немножко проще закидывать байты — не нужно сдвигать байт, зато в четырех битном резко нужно тратить на целых четыре ножки контроллера меньше. Есть еще одна особенность работы в 8-битном режиме — к некоторым контроллерам можно подрубить этот дисплей как внешнее ОЗУ и засылать данные простыми командами пересылки. Лично я подключил его в режиме полного порта у меня один фиг выводы уже девать некуда было, так что не жалко.
  • Выводы DB7…DB0 это шина данных/адреса.
  • E — стробирующий вход. Дрыгом напряжения на этой линии мы даем понять дисплею что нужно забирать/отдавать данные с/на шину данных.
  • RW — определяет в каком направлении у нас движутся данные. Если 1 — то на чтение из дисплея, если 0 то на запись в дисплей.
  • RS — определяет что у нас передается, команда (RS=0) или данные (RS=1). Данные будут записаны в память по текущему адресу, а команда исполнена контроллером.

Со стороны питания все еще проще:

Подключение дисплея
Подключение дисплея
Видимая и скрытая область экранной памяти
Видимая и скрытая область экранной памяти
Структура адресации контроллера HD44780
Структура адресации контроллера HD44780
Формирование символа в ячейке CGRAM
Формирование символа в ячейке CGRAM

  • GND — минус, он же общий.
  • Vcc — плюс питания, обычно 5V
  • V0 — вход контрастности. Сюда нужно подавать напряжение от нуля до напряжения питания, тем самым задается контрастность изображения. Можно поставить переменный резистор, включенный потенциометром и крутить в свое удовольствие. Главное поймать значение максимального контраста, но чтобы не было видно знакомест (серый ореол из квадратов вокруг символа). Если же выставить слишком малый контраст, то символы будут переключаться лениво и задумчиво. Примерно как в калькуляторе у которого сели батарейки.
  • А — это вход Анода светодиодной подсветки. Короче плюс.
  • К — соответственно Катод, он же минус. Подсветка хавает примерно 100мА и поэтому нужно выставить туда токоограничительный резистор на 100 Ом. Кстати, многие ЖК дисплеи имеют на плате пятачки для припайки резисторов. Если прозвонить, то можно убедиться в том, что эти линии ведут на входы питания LCD, поэтому, впаяв резисторы, можно не заморачиваться на запитку подстветки, она будет подключена к питанию контроллера.

Логическая структура LCD контроллера HD44780

Контроллер имеет свой блок управления, который обрабатывает команды и память. Она делится на три вида:

DDRAM — память дисплея. Все что запишется в DDRAM будет выведено на экран. То есть, например, записали мы туда код 0x31 — на экране выскочит символ «1» т.к. 0х31 это ASCII код цифры 1. Но есть тут одна особенность — DDRAM память гораздо больше чем видимая область экрана. Как правило, DDRAM содержит 80 ячеек — 40 в первой строке и 40 во второй, а на дисплей может двигаться по этой линейке как окошко на логарифмической линейке, высвечивая видимую область. То есть, например, можно засунуть в DDRAM сразу пять пунктов меню, а потом просто гонять дисплей туда сюда, показывая по одному пункту. Для перемещения дисплея есть спец команда. Также есть понятие курсора — это место в которое будет записан следующий символ, т.е. текущее значение счетчика адреса. Курсор не обязательно может быть на экране, он может располагаться и за экраном или быть отключен вовсе.

CGROM — таблица символов. Когда мы записываем в ячейку DDRAM байт, то из таблицы берется символ и рисуется на экране. CGROM нельзя изменить, поэтому важно, чтобы она имела на борту русские буквы. Если, конечно, планируется русскоязычный интерфейс.

CGRAM — тоже таблица символов, но ее мы можем менять, создавая свои символы. Адресуется она линейно, то есть вначале идет 8 байт одного символа, построчно, снизу вверх — один бит равен одной точке на экране. Потом второй символ тем же макаром. Поскольку знакоместо у нас 5 на 8 точек, то старшие три бита роли не играют. Всего в CGRAM может быть 8 символов, соответственно CGRAM имеет 64 байта памяти. Эти программируемые символы имеют коды от 0х00 до 0х07. Так что, закинув, например, в первые 8 байт CGRAM (первый символ с кодом 00) какую нибудь фигню, и записав в DDRAM нуль (код первого символа в CGRAM) мы увидим на экране нашу хрень.

Доступ к памяти.
Тут все просто. Мы командой выбираем в какую именно память и начиная с какого адреса будем писать. А потом просто шлем байты. Если указано, что записываем в DDRAM то на экран (или в скрытую область) полезут символы, если в CGRAM то байты полезут уже в память знакогенератора. Главное потом не забыть переключится обратно на область DDRAM

Система команд.
Система команд проста как мычание. О том, что передается команда контроллеру дисплея сообщит нога RS=0. Сама команда состоит из старшего бита, определяющего за что отвечает данная команда и битов параметров, указывающих контроллеру HD44780 как дальше жить.

Таблица команд:

DB7DB6DB5DB4DB3DB2DB1DB0Значение
00000001Очистка экрана. Счетчик адреса на 0 позицию DDRAM
0000001Адресация на DDRAM сброс сдвигов, Счетчик адреса на 0
000001I/DSНастройка сдвига экрана и курсора
00001DCBНастройка режима отображения
0001S/CR/LСдвиг курсора или экрана, в зависимости от битов
001DLNFВыбор числа линий, ширины шины и размера символа
01AGAGAGAGAGAGПереключить адресацию на SGRAM и задать адрес в SGRAM
1ADADADADADADADПереключить адресацию на DDRAM и задать адрес в DDRAM

Теперь поясню что значат отдельные биты:
  • I/D — инкремент или декремент счетчика адреса. По дефолту стоит 0 — Декремент. Т.е. каждый следующий байт будет записан в n-1 ячейку. Если поставить 1 — будет Инкремент.
  • S — сдвиг экрана, если поставить 1 то с каждым новым символом будет сдвигаться окно экрана, пока не достигнет конца DDRAM, наверное удобно будет когда выводишь на экран здоровенную строку, на все 40 символов, чтобы не убегала за экран.
  • D — включить дисплей. Если поставить туда 0 то изображение исчезнет, а мы в это время можем в видеопамяти творить всякие непотребства и они не будут мозолить глаза. А чтобы картинка появилась в эту позицию надо записать 1.
  • С — включить курсор в виде прочерка. Все просто, записали сюда 1 — включился курсор.
  • B — сделать курсор в виде мигающего черного квадрата.
  • S/C сдвиг курсора или экрана. Если стоит 0, то сдвигается курсор. Если 1, то экран. По одному разу за команду
  • R/L — определяет направление сдвига курсора и экрана. 0 — влево, 1 — вправо.
  • D/L — бит определяющий ширину шины данных. 1-8 бит, 0-4 бита
  • N — число строк. 0 — одна строка, 1 — две строки.
  • F — размер символа 0 — 5х8 точек. 1 — 5х10 точек (встречается крайне редко)
  • AG — адрес в памяти CGRAM
  • АD — адрес в памяти DDRAM

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

Задача:

  1. Включить дисплей.
  2. Очистить содержимое.
  3. Сдвинуть курсор на одну позицию.
  4. И записать туда «1».
Решение (последовательность команд):

Первым делом Инициализация дисплея без которой большая часть дисплеев на HD44780 просто откажется работать. Некоторые виды имеют дефолтные состояние (шина 8 бит, курсор в 0) и им только дисплей включить. Но все же ее лучше сделать, мало ли что там намудрил разработчик. Лишней не будет.

  1. 00111000 Шина 8 бит, 2 строки
  2. 00000001 Очистка экрана
  3. 00000110 Инкремент адреса. Экран не движется

  1. 00001100 Включили дисплей (D=1)
  2. 00000001 Очистили дисплей. Указатель встал на DDRAM
  3. 00010100 Сдвинули курсор (S/C=0) вправо (R/L=1)
  4. 00110001 — это мы уже записали данные (ножка RS=1) код «1» 0х31

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

Задача: создать свой символ. С кодом 01 и вывести его на экран.
Считаем, что дисплей у нас уже инициализирован и готов к приему данных.

Решение:

  1. 01001000      Выбираем в CGRAM адрес 0х08 — как раз начало второго символа (напомню, что на один символ уходит 8 байт)
  2. 00000001     Это пошли 8 байт данных. (RS=1)
  3. 00000010     Рисуем значок молнии, ну или
  4. 00000100     ССовскую Зиг руну, кому как
  5. 00001000     больше нравится.
  6. 00011111     Старшие три бита не действуют
  7. 00000010     Туда можно писать что угодно, на
  8. 00000100     результат влиять не будет.
  9. 00001000     Последний байт данных  
  10. 10000000      А это уже команда — переключение адреса на DDRAM и указатель на адрес 0000000 — первый символ в первой строке.
  11. 00000001      И снова данные (RS=1), код 01 — именно в него мы засунули нашу молнию.
Опа и он на экране!

Так, с логикой разобрались, пора вкуривать в физику протокола общения. Код я приведу несколько позже, когда вылижу свою библиотеку и заоптимизирую до состояния идеала. Пока же дам алгоритм, а его уж на любом языке программирования реализовать можно. Хоть на ассемблере, хоть на Сях, да хоть на Васике :)

Алгоритм чтения/записи в LCD контроллер HD44780
Направление, а также команда/данные определяются ножками, а чтение и запись осуществляется по переходу строба (вывод Е) из 1 в 0

Инициализация портов

  1. RS, RW, E — в режим выхода.
  2. DB7..DB0 в режим входа. Впрочем, можно их не трогать, дальше переопределим.


Ожидание готовности, чтение флага занятости.
  1. Порт данных на вход с подтяжкой (DDR=0, PORT=1)
  2. RS=0 (команда)
  3. RW=1 (чтение)
  4. E=1 (Готовьсь!!!)
  5. Пауза (14 тактов процессора на 8МГЦ хватало)
  6. Е=0 (Пли!)
  7. Читаем из порта. Если бит 7 (Busy flag) установлен, то повторяем все заново, пока не сбросится.


Запись команды
  1. Ожидание готовности
  2. RS=0 (команда)
  3. RW=0 (запись)
  4. Е=1 (Готовьсь!!!)
  5. Порт на выход
  6. Вывести в порт код команды
  7. Пауза
  8. Е=0 (Пли!)
  9. Орудие на плечо Порт на вход, на всякий случай.


Запись Данных
  1. Ожидание готовности
  2. RS=1 (Данные)
  3. RW=0 (запись)
  4. Е=1 (Готовьсь!!!)
  5. Порт на выход
  6. Вывести в порт код команды
  7. Пауза
  8. Е=0 (Пли!)
  9. Порт на вход, на всякий случай.


Чтение команды
  1. Ожидание готовности
  2. Порт данных на вход с подтяжкой (DDR=0, PORT=1)
  3. RS=0 (команда)
  4. RW=1 (чтение)
  5. Е = 1 (Готовьсь! В этот момент данные из LCD вылазят на шину)
  6. Пауза
  7. Считываем данные с порта
  8. E=0 (Ать!)


Чтение Данных
  1. Ожидание готовности
  2. Порт данных на вход с подтяжкой (DDR=0, PORT=1)
  3. RS=1 (Данные)
  4. RW=1 (чтение)
  5. Е = 1 (Готовьсь! В этот момент данные из LCD вылазят на шину)
  6. Пауза
  7. Считываем данные с порта
  8. E=0 (Ать!)

С четырех разрядной шиной все точно также, только там каждая операция чтения/записи делается за два дрыга строба.

Запись:

  1. E=1
  2. Пауза
  3. Выставили в порт старшую тетраду
  4. E=0
  5. Пауза
  6. Е=1
  7. Пауза
  8. Выставили в порт младшую тетраду
  9. Е=0


Чтение
  1. E=1
  2. Пауза
  3. Читаем из порта старшую тетраду
  4. Е=0
  5. Пауза
  6. Е=1
  7. Пауза
  8. Читаем из порта младшую тетраду
  9. Е=0

Ждите код :) Скоро будет :)
UPD:
А вот и код!

315 thoughts on “AVR. Учебный курс. Подключение к AVR LCD дисплея HD44780”

  1. Однако познавательно! Как только появится свободное время, надо будет это все расковырять =) Как раз 8ю атмегу в ДИПе достану и панельу к ней. Надо будет спаять какую-нить полезную хреновину =) В любом случае спасибо автору. Он и на этот раз не подвел. Толковые вещи пишешь =)

    1. Уважаемый автор! Спасибо за прекрасную статью.Прошёлся по ней несколько раз,но чем определяется видимая область-не нашёл или не понял.Пожалуйста поясните.Заранее благодарен. frolov.

        1. Это понятно,но с какого адреса начинается видимая область?Например,заносим информацию по адресу 0x20 8 знаков,затем ровно под ней по адресу 0x40 ещё 8 знаков(это по вашему рисунку).Потом включаю дисплей. Чтобы то,что я занёс было на экране нужно-ли вставать на адрес 0x20? А если я встану на адрес 0x10? Изменится видимая область? Если так,то с какой стороны от адреса она окажется с левой или правой,зависит-ли это от включенности инкремента или декремента. Извини DI HALT но я живу в маленьком городе,дисплея пока нет,заказал.Когда будет неизвестно,а код пишу,вот и возникают такие вопросы.Извини за назойливость.Спасибо.

          1. А вот как и нарисовано. Т.е. в первой строке с 0х00, а во второй — 0х40. Это при включении, если ничего не трогать. Потом, командами, можешь окно двигать. Инкремент это вроде бы сдвиг вправо, декремент влево. Никогда с этими окнами отображения не заморачивался. Предпочитаю сделать видеопамять в ОЗУ контроллера и все.

          2. Спасибо DI HALT! Чуть прояснилось.Ещё раз понял,что лучшая форма обучения-это самообучение.Как сказал Иртеньев
            Всё накрылось медным тазом,
            Но покуда тлеет разум
            Ощущения конца
            Всё же нету до конца.

        2. Уважаемый Di Halt. Спросить не у кого,если не трудно ответь. Никогда не занимался с mega8.Может быть у неё есть какие-нибудь особенности.Я просто растерялся. Как будто с мегой32 когда включен jtag.Но в меге8 jtaga нет.В чём может быть причина. В симуляторе avr studio всё хорошо,а после прошивки ничего даже близкого нет. Посоветуй.

        3. Уважаемый Di Halt. Поздравляю Вас с Праздником,правда как его правильно назвать-уже не знаю. Всю свою жизнь отдал оборонке, а названия увы.Прочитал Вашу статью про ЦАП. Ответьте пожалуйста как конфигурировать ноги МК к которым подключен R-2R? Ответьте. Если что неправильно спросил,то извините.

          1. Уважаемый Di Halt! Сегодня всё утро искал Push-Pul,но ничего конкретного не нашёл. Если не трудно,черкни пару строк на ассемблере для примера.Сложно,если вырос на минск-22, осваивать МК. Другой уровень абстракции. Спасибо.

  2. Поздравляю с Днём Рождения!!!
    Успехов тебе в твоих начинаниях!
    Пишешь очень интересно и понятно.
    Читаю все твои статьи с огромным интересом. Особенно порадовала серия рассказов «Последний Герой труда».

    1. +1

      есть минивопрос — имеются ли в реальности лсд-дисплеи на 3 вольта?

      зы! прошёлся по питерским магазам типа микроники и чипидипа — у них не бывает. а сами дисплеи на 2 строки начинаются от 400 рублей (

        1. может просто неудачный день. хотя тут же на днях покупал мегу8535 — 170рэ, а с буковкой L — ровно в 2 раза дороже. это с учётом того, что зимой мне знакомый из москвы из по 100рублей привозил … (

              1. эта мега мне не нужна уже )
                а про 3В спросил вот почему — как раз с мегой (которая L, которая на 3В) достал корпус, который выглядит, как старый большой калькулятер.

                толстый такой, с уже вырезанным окошком. под него в магазе и пытался подобрать жк — мне бы любой подошёл, лишь бы влез. как обычно — были или очень большие, или не было нужный ) все почему-то дорогие, все на 5В.

                минус — на сайте ихнем не написан вольтаж, а матчастью по этому поводу я не знаком, так что поиски по времени ещё больше удлиняются (

                    1. Работать напрямую от батареек будет, но недолго :D
                      Напряжение разряженной батареи — 1В, девайс сдохнет задолго до конца ее разряда.
                      Для батарейного питания ставят повышающие DC-DC преобразователи типа MAX1674-MAX1676.

                    2. На входе — от 0.7В до 3В, на выходе — стабильные 3.5В или 5В, нужное напряжение выбирается.

      1. Попробуйте МЭЛТ — они могут работать на трёшке, но с более длинными таймаутами.
        Но учтите, что инициализация несколько отличается от чистого hd44780, в остальном они совместимы.

  3. Почти во всех ЖКИ-модулях, в том числе и в ЖКИ-модулях с HD44780, перед началом работы, обязательно необходима начальная инициализация, без этого он просто не будет работать. Мб автор просто забыл про это, а может просто взял какой-то левый даташит на HD44780, тк встречал я один даташит на русском по HD44780, там было указано, что активируется ЖКИ-модуль вращением подстроечного резистора, что не является правильным, поэтому я бы посоветовал читать оригинальные даташиты, а не переведённые непонятно кем, если это было так.

    1. Да забыл. Добавил. Хотя мой дисплей (вот тот который на фотке) имеет дефолтные значения, я сам удивился когда он заработал сразу же после того как я ему врубил дисплей. Даташиты на русском зло. Мало того, что в оригинальных бывают баги, так еще и переводчики накосячат.

  4. Поздравляю с днем рождения, желаю творческих успехов, и восхищаюсь терпением излагать всю эту информацию подробно и доходчиво! Сам занимаюсь AVR-ами примерно два года, и если бы кто-нибудь тогда мне все вот так расписал… :)

  5. Еще покомментирую. Дисплеи на HD44780 бывают очень разные по времени реакции на строб. Обычно дисплеи, рассчитанные на 3В, более медленные, чем на 5В, и требуют более длинных задержек при работе с ними. Удивительно, но по сравнению с HD44780 те же графические контроллеры KS0713 несмотря на бОльший объем передаваемой информации, оказались гораздо быстрее в работе — обновление монохромного экрана 128х64 занимает совсем не много времени. Очень рекомендую внимательно присмотреться к этому семейству… туда можно вывести значительно больше информации, чем на любой текстовый дисплей. И само собой, они прекрасно интерфейсятся с АВР-ами :)

    1. Они там уже года два как — там раньше их оптовая база была. С торца здания 2А есть здоровенная железная дверь, похожая на гараж. Вот в нее и сразу же направо. Я тоже первый раз долго искал.

  6. Тут спрашивали по поводу 3.3В дисплеев, HD44780 может работать и от 3.3В , но только сам контроллер, для того чтобы было видно что то на дисплее, надо подавать отрицательное напряжение на вход управления контрастом. Или брать расчитанный на 3.3В изначально (по опыту поиска огромный дефицит :) )
    Можно еще использовать от Nokia дисплеи (3310, 3410), но они графические поэтому для вывода символа надо писать свою библиотеку (в инете полно готовых), еще очень хорошие TIC32 и TIC149 тоже графические но работают как от 3.3 так и от 5В.
    Буква L в индексе контроллера указывает что он может работать от 3В , от 5В он тоже работает нормально :)

  7. Есть такой вопрос, может кто-нибудь сталкивался:
    Работаю с МЭЛТ’овским ЖКИ-модулем MT-16S2R, у него контроллер КБ1013ВГ6 (аналог HD44780 и KS0066).

    При работе с ним выявилась проблема, заключающаяся в том, что флаг занятости как бы зависает после команд записи в DDRAM. Т.е. я записываю какие-то данные в DDRAM и проверяю в цикле флаг ожидания, и пока он не станет равен нулю, те контроллер не будет готов выполнить следующую команду, дальше ничего не делаю.
    Но дело в том, что этот флаг после записи данных в DDRAM не устанавливается в 0 сколько не жди, т.е. все время показывает, будто контроллер занят. Хотя если сделать не проверку флага занятости, а просто задержку времени в 40мкс (это максимальное время записи в DDRAM по документации), то он нормально записывает данные в DDRAM и готов выполнить следующую команду.
    Но тот же флаг занятости при выполнении обычной команды, которая не изменяет DDRAM, нормально показывает занят контроллер или нет.
    Флаг занятости также как и в случае с записью в DDRAM, не изменяется после выполнения команды установки адреса для последующих операций и выбора области DDRAM.
    Похоже, что флаг занятости не изменяется контроллером, если выполнялось какое-то изменение в DDRAM.
    В документации на ЖКИ-модуть и на контроллеры КБ1013ВГ6 и HD44780 (на KS0066 я не смотрел) ничего об этом не сказано, поэтому я и хотел спросить, не встречался ли кто с подобным?
    Если кто-то сталкивался с подобным, я был бы очень признателен за разъяснение этой ситуации.

    Сам просто стал проверять флаг занятости только после команд, не изменяющих DDRAM, а для тех, что изменяют DDRAM делал задержку.
    Собственно кусок кода проверки флага занятости:
    8-битный интерфейс. PORTA — шина данных, PINC5 — RS, PINC6 — R/W, PINC7 — E:

    CBI PORTC, 5
    L0:
    SBI PORTC, 6
    SBI PORTC, 7
    NOP
    NOP
    IN TMP_PRG, PORTA
    ANDI TMP_PRG, 0B10000000
    CBI PORTC, 7
    CBI PORTC, 6
    CPI TMP_PRG, 0
    BRNE L0

    1. Я работаю с МЭЛТами. Ничего подобного за ними не замечал. Флаг занятости успешно выставляется как после записи в DDRAM, так и при любой другой операции.
      Нет возможности проверить на другом модуле?

        1. Проверять на другом модуле не пришлось, нашел ошибку у себя в коде )
          Нужно было правильно сделать проверку флага занятости так:
          CLR TMP_PRG
          OUT DDRA,TMP_PRG
          OUT PORTA,ZERO
          Label:
          SBI PORTC, 6
          SBI PORTC, 7
          NOP
          NOP
          IN TMP_PRG, PINA
          ANDI TMP_PRG, 0B10000000
          CBI PORTC, 7
          CBI PORTC, 6
          CPI TMP_PRG, 0
          BRNE Label
          SER TMP_PRG
          OUT DDRA,TMP_PRG
          А я забыл очистить содержимое порта, после того, как выводил в ЖКИ команды установки адреса для последующих операций и выбора области DDRAM и после записи данных в DDRAM, поэтому бит занятости оставался равным единице все время.

  8. Управление LCD-дисплеем HD44780 по одному проводу
    Автор Noureddine Benabadji
    18.03.2008 г.
    LCD-дисплеи с контроллером HD44780 являются пожалуй одними из самых популярных символьных дисплеев для встраиваемых систем. Единственным их недостатком можно считать необходимость задействования для управления дисплеем шести I/O-линий микроконтроллера в 4-разрядном режиме либо одиннадцати I/O-линий в 8-разрядном режиме. Для сокращения числа управляющих линий можно использовать преобразователи последовательного кода в параллельный на основе стандартной логики. Однако, управлять HD44780-совместимыми LCD-дисплеями можно даже по одной линии. Такую функцию гораздо удобнее возложить не на микросхемы жёсткой логики, а на программируемый микроконтроллер, сократив, таким образом, стоимость и занимаемую схемой на печатной плате площадь. Этим целям в полной мере удовлетворяют микроконтроллеры Microchip серии PIC10F в миниатюрном корпусе SOT23–6.

    Схемотехническое решение, показанное на рисунке, может оказаться полезным для многих встраиваемых систем с ограниченным числом выводов, потому как способно управлять HD44780-совместимыми LCD-дисплеями посредством однопроводной линии передачи данных, задействуя простой асинхронный RS232 протокол на скорости 9600baud. В схеме применён PIC10F202, но подойдёт любой микроконтроллер из этого семейства, потому что хорошо оптимизированный программный код (прошивка 1) состоит из всего лишь 256 слов. Увеличить скорость выше 9600baud не представляется возможным, так как PIC10F202 содержит внутренний RC-генератор с точностью 1%, а LCD-дисплей требует задержку длиной 1.6ms для некоторых инструкций, таких как «очистка дисплея». Программный код представлен в виде исходников с комментариями для LCD232 модуля; основная программа состоит из дисплейной заставки на 2 секунды и дальнейшего бесконечного цикла для ожидания 1 байта команды, максимум 16 байт данных и нуля ASCII. В тестовых целях сопряжения дисплея с внешней встраиваемой PIC-системой можно воспользоваться простой прошивкой на ассемблере (прошивка 2).

  9. Как раз вчера-позавчера ковырял индикатор BC1602, долго думал почему он у меня не хочет работать, заодно нашел опечатку в статье.

    >># 01001001 Выбираем в CGRAM адрес 0х09 — как раз начало второго символа (напомню, что на один
    >>символ уходит 8 байт)

    Начало второго символа это 1000, а не 1001. Т.е. первый символ — 01000000, второй — 01001000, третий 01010000 и т.д.

    А у меня не работал потому, что я на ногу контрастности подавал 2,5В, а он, сцуко, после ~1,1В перестает показывать. Два дня парился, пока не догадался подключить переменный резистор на контрастность… :(

    P.S.
    >>Всего в CGRAM может быть 8 символов, соответственно CGRAM имеет 64 байта памяти. Эти программируемые символы имеют коды от 0х00 до 0х08.

    Если их 8, то от 0х00 до 0х07

  10. Приветствую! Прекрасная статья по LCD!

    Теперь по теме:

    В тексте
    >I/D — инкремент или декремент счетчика адреса. По дефолту стоит 0 — инкремент. Т.е. >каждый следующий байт будет записан в n+1 ячейку. Если поставить 1 — будет декремент.

    присутствует ошибка.
    Все наоборот.
    I/D=1 — инкремент (0 — декремент)

    Обоснование — пример из datasheet на KS0066U (Samsung):

    I/D: Increment / decrement of DDRAM address (cursor or blink)
    When I/D = “ High” , cursor/blink moves to right and DDRAM address is increased by 1.
    When I/D = “ Low” , cursor/blink moves to left and DDRAM address is decreased by 1.

    1. delay_ms(100);
      lcd_com(0b00111111);
      delay_ms(10);
      lcd_com(0b00111111);
      delay_ms(10);
      lcd_com(0b00111111);
      delay_ms(10);
      lcd_com(0b00111000);
      delay_ms(1);
      busy();
      lcd_com(0b00001000); /*!!!*/
      delay_ms(1);
      busy();
      lcd_com(0b00000001);
      delay_ms(1);
      busy();
      lcd_com(0b00000110);
      delay_ms(1);
      busy();
      lcd_com(0b00001100); /*vkl*/
      busy();

    1. Или пока фузы не залочишь ;)

      Мой те совет — шей ее через бутлоадер STK500 (написано что она уже прошита им). В таком случае убить ее надо постараться. Бутлоадер ничего критичного сделать с МК не сможет.

    1. Бутлоадер это такая микропрошивка (не более 2кб) распологается в специальной области памяти. При старте вначале стартует бут, он по UART (Com порт или USB2COM) засасывает в себя прошивку и сам ее размещает в памяти.

      После прошивки бут стартует МК уже с залитого кода.

    1. Да нет, взял подключился обычным программатором по ISP и снес бут вместе со всей прошивкой нахрен. Ну или обратно его вернул. Или вообще другой поставил. Но я тебе пока это не рекомендую — одно неосторожне движение с fuse и ты заблокировал кристал наглухо.

  11. Да, бутлоадер при старте слушает порт. Если в течении какого то времени не произошло ничего — стартует основную прошивку.

    А студия отслеживает наличие ответа бута на порту.

    Обычно делается как. Ты жмешь на контроллере RESET и в течении секунды-двух тебе надо нажать на кнопку в студии (или наоборот) и тогда бут и студия найдут и поймут друг друга.

  12. Не, DI. Тебе явно надо в преподы идти, причем к олегофренам.:))))))))))) Так мне даже в живую никто не обьяснял. Я про сайт вообще и про МК в частности! Спасибо большое!!! :)

      1. Ты был преподавателем? Прикольно. Что преподавал то? Ассемблер? Да современным преподам тяжело, сегодня в этой сфере нужно иметь нервы еще те (железные). Новое поколение становится все более деградированное. Если не построить сразу, потом на шею сядут и на голову все вместе.

        Прикупил сегодня дисплей на 2×16. 270 руб. Будем запускать по написанному… в космос…

  13. А можно проконсультроваться? Нашел тут схемку для подключения HD44780 с управлением контрастностью и подсветкой через контроллер:

    http://www.harbaum.org/till/lcd2usb/schematic.gif

    Был бы очень признателен за комментарий относительно корректности данного решения (контрастность — через LC контур, подсветка — через транзистор и токоограничительные резисторы). Особенно интересует LC контур: вроде бы понятно, что он там для сглаживания сигнала с PWM, но к сожалению, ограниченные знания не позволяют дотумкать, почему сам контроллер фактически включен _внутрь_ контура.

    1. Вполне корректно. НА контраст таким образом подается ШИМ напряжение сглаженное LC фильтром. Вместо индуктивности там, думаю, можно вкрутить сопротивление на 1К, должно работать не хуже.

      А с LC как получается — чтобы не пожечь выход МК надо ограничивать ток заряда/разряда конденсатора. Тут индуктивность ограничивает ток, а кондер гладит напряжение.

  14. Полезная статья!
    а вот Мой случай.
    Купил как то
    HY-1601C-405… дальше не важно…
    Как видно 16 символов 1 строка
    Как ни бьюсь, не могу включить
    вторые восемь символов.
    После установки в FUNCTION Set
    еденицы, отвечающей за 2 строки
    Инициализация проходит так что
    на экране и первая строка
    пропадает.
    Может кто сталкивался с
    таким индикатором?

    1. Во-во. И у меня такая проблема. Экран WM С-1601 шестнадцать символов, одна строка. Влкючаются только первые восемь символов. Экран на HD44780. Работаю по 8бит. Может быть такое, что для инициализации однострочных экранов какие-то другие каманды? Или экран битый? Если он не правильно инициализирован при регулировке контраста должны быть видны все символы? У меня только 8 видно? В чем может быть проблемма?

      P.S. АВТОРУ САЙТА: Сайт классный, читаю не нарадуюсь. Всё разжевано до нельзя. Так держать. Молодец!!!!!!!!!!!

        1. Всем спасибо, разобрался. Перед инициализацией поставил задержку, загорелись обе половинки. А он оказывается устроен полностью как двухстрочный. Первые 8 символов — 1я первая строка, вторые 8 символов — 2я строка. Блин. Это дибилизм какой-то. Очень не удобно работать когда 9-ый символ находится почти в 40-а ячейках от восьмого. О чем думали создатели…

      1. Если особо запариться то можно, каждый раз эти 8 символов перезаписывать теми буквами которых не хватает. А если еще немного запариться то можно 16 перезаписывать, только прога будет постоянно занята работой с дисплейем.
        См. комент ниже Dimas D 13 Дек 2009 12:33

  15. Здравствуйте.
    Долго изучал Ваши материалы. Все. Спасибо за работу и желание поделиться с другими. Но, сегодня встретился с проблемой решение которой пока не нашел, поэтому обращаюсь к Вам. Подскажите, пожалуйста, как организовать обмен информацией между AG12232A и ATmega8535 — 16PU. Буду благодарен за любую информацию.
    С уважением, MiD

    1. Попробуй сделать инициализацию дисплея не сразу, а спустя 100ms после старта МК. Или запусти всю плату, а потом сделай сброс контроллеру, чтобы дисплей успел инициализироваться.

      Вообще если квадратики есть, значит вроде как рабочий. Если нигде не затупил с кодом, то должно работать.

      Можешь мою либу попробовать подключить. Я ей уже производителей 5 разных дисплеев опробовал — везде работает четко ,как надо.

  16. Ммм Благодаря танцам с бубном вопрос снят но для меня загадка (почему :) так как ни инициализация с даной статьи ни с дататашита 2 дня не проходила :) а сегодня сцуко взяло и заработало хотя со вчера ни чего не менял кроме как устанувил ожидание нажатия кнопки перед каждим шагом инициализации… Имхо проблема что вибрал слишком маленькие паузи между шагами… хотя хз)

  17. Автору респект биг спс за статьи!
    Имхо в макросах в макросе WR_CGADR
    Лучше указать LDI R17,(1<<LCD_CGRAM)|(@0*8)

    И ещо подскажите как вивесть строку я вивожу таким макросом:
    .MACRO WR_MSG
    LDI ZH,High(@0*2)
    LDI ZL,Low(@0*2)
    WR_MSG_Load: LPM R17, Z+
    CPI R17,0
    BREQ WR_MSG_End
    RCALL DATA_WR
    RJMP WR_MSG_Load

    WR_MSG_End:
    .ENDMACRO

    Собствено сам вивод:
    msg: .db «Ready»,0
    WR_MSG msg

    Всё виводит но интересует может есть более оптимальний способ

    1. .MACRO WR_MSG
      LDI ZH,High(@0*2)
      LDI ZL,Low(@0*2)
      RCALL MSG_WR
      .ENDMACRO

      .MACRO WR_NewS ; Position, symbol
      WR_CGADR @0
      LDI ZH,High(@1*2)
      LDI ZL,Low(@1*2)
      RCALL MSG_WR
      .ENDM

      MSG_WR: LPM R17, Z+
      CPI R17,0
      BREQ MSG_WR_End
      RCALL DATA_WR
      RJMP MSG_WR
      MSG_WR_End: RET

      Собственно работает так
      msg: .db «Ready»,0
      s1: .db 1,2,4,31,2,4,8,16,0,0 ; символ Flash
      sii: .db 32,32,10,32,4,4,4,32,0,0 ; символ ї

      WR_MSG msg

      WR_NewS 0,s1
      WR_NewS 1,sii

      LCD_COORD 0,1
      WR_DATA 0
      WR_DATA 1

  18. По поводу 3В питания:
    есть у меня дисплей WH1602B-YGK-CTK WINSTAR(2 строки по 16 символов), расчитанный на 5В, но я особо не парился и всегда его подключал на 3.3В по стандартной схеме и сопротивление контрастности тоже включал между 3.3 и 0. Работает замечательно.

    Еще на нем график рисовал (можно вообще любой рисунок делать), для этого есть графические дисплеи, но они дороже:
    суть следующая можно просто в перезаписываемые символы занести то что надо и отобразить, но их всего 8(, а хотелось как минимум 16. Для этого поступал сдедующим образом:
    в первой строке 8 символов, а во второй отображал 8 черных квадратов, перезаписывал символы
    и делал наоборот: в первой стороке черные а во второй записанные символы.
    Потом настраиваем контрастность так что бы фон черного квадрата не был видет, при этом выглядит это не плохо, от обычных символо трудно отличить.
    Зы: можно сделать и 24 спецсимвола но контрастность будет не очень, а при 32 вообще фигня.
    Только обязательно заменять черным квадратом, если белым менять то в символах точки получались с разным оттенками)

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

  19. Доброе время суток!
    Может я немного не по теме, но собрал я тут одну приколюху для подключения
    LCD дисплея к компу по USB на меге-8
    http://www.harbaum.org/till/lcd2usb/index.shtml
    Всё чудесно кроме отображения русских символов.
    Дисплей с русским знакогенератором.Может его инициализировать както по другому надо?
    Не подскажете? Исходники прошивки и драйвера имеются.

  20. Доброе время суток!
    У меня возникла проблема с ЛСД.Первый ряд подмигивает а второй маргает .Общую частоту
    задержек пробовал именять чуть луше стало.В противном случае реже маргает или второй
    ряд становится блеклым.4 бита система контрасность на максимуме

  21. Написал программу. Тут и инициализация и заносим некоторые данные.
    Помогите ее довести до ума. Чего не хватает, что где добавить и почему так.
    Я только учусь ассемблеру.
    И зачем считывать флаг занятости и что это вообще и для чего он нужен.
    ЗАРАНЕЕ ОГРОМНОЕ СПАСИБО!!!
    Итак, код:

    ; LCD
    —————————————
    ; Инициализация дисплея
    —————————————
    .def Temp=R16
    .def Temp1=R17
    .def Temp2=R18
    .def Temp3=R19
    .def Temp4=R20

    .cseg
    .org 0

    ; RS = 0bits portc
    ; E = 1bits portc
    ; RW = 2bits portc

    ; Подключили питание
    rcall delay1s ; Выжидаем 1 секунду
    ldi Temp, 0b11111111
    out ddrc, temp ; Настройка портов C
    ldi Temp1, 0b11111111
    out ddrd, temp1 ; Настройка портов D

    sbi portc, 1 ; Устанавливаем Е в 1 (пока что готовимся)
    cbi portc, 2 ; Сбрасываем RW в 0 (режим записи)
    cbi portc, 0 ; Сбрасываем RS в 0 (режим занесения команд)

    ldi temp1, 0b00110000 ; загружаем настройки разрядности
    out portd, temp1 ; выводим ее в lcd
    cbi portc, 1 ; Поехала первая команда в LCD
    rcall delay50mks ; Ждем 50мкс (немного выше, чем нижний предел)

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00110000 ; Снова настройки разрядности
    out portd, temp1 ; выводим в LCD
    cbi portc, 1 ; выдаем в дисплей, строб
    rcall delay50mks ; снова ждем 50мкс

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00110000 ; Снова настройки разрядности
    out portd, temp1 ; выводим в LCD
    cbi portc, 1 ; выдаем в дисплей, строб
    rcall delay50mks ; снова ждем 50мкс

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00111000 ; устанавливаем 8разр. шина данных, две строки, размер матрицы — 5х8т
    out portd, temp1; Выводим
    cbi portc, 1 ; Пли!!! Строб
    rcall delay50mks ; Пауза

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00001000 ; Выключаем дисплей
    out portd, temp1 ; Выводим
    cbi portc, 1 ; Пли!!! Строб
    rcall delay50mks ; Пауза

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00000001; Очистка дисплея
    out portd, temp1 ; Выводим
    cbi portc, 1 ; Пли!!! Строб
    rcall delay1ms ; Пауза в 1 милисекунду

    sbi portc, 1 ; опять строб на 1

    ldi temp1, 0b00000110 ; Курсор сдвигается вправо, без сдвига экрана
    out portd, temp1 ; Выводим
    cbi portc, 1 ; Пли!!! Строб
    rcall delay50mks ; Пауза

    ;—————————————
    ;Инициализация, конец
    ;—————————————

    ;—————————————
    ;Что-нибудь выведем
    ;—————————————

    sbi portc, 1 ; опять строб на 1
    sbi portc, 0 ; Теперь работаем с данными

    ldi temp1, 0b10100101 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;
    sbi portc, 1 ;
    ldi temp1, 0b10111011 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b11000100 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10111000 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10111101 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b01000101 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10110011 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10110100 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b01100101 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10111101 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b110111000 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1 ;
    ldi temp1, 0b10111001 ;
    out portd, temp1 ;
    cbi portc, 1 ;
    rcall delay50mks ;

    sbi portc, 1;

    cbi portc, 0 ; работа с командами:

    ldi temp1, 0b00001100 ; Включаем дислпей
    out portd, temp1 ; Выводим
    cbi portc, 1 ; Пли!!! Строб
    rcall delay50mks ; Пауза

    sbi portc, 1; Е в 1

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

  22. Это, например, в том случае, если задержку сделал меньше минимально допустимой, например, 30мкс, вместо 40мкс?

    Приведи пример кода, как и КОГДА надо проверять флаг занятости…

    И что с кодом — все правильно?

  23. Посмотри, пожалуйста. Внеси изменения, если таковы требуются. Если, конечно же у тебя есть время))) (надеюсь будет).
    Просто я пытаюсь учить ассемблер путем изобретания велосипедов :)

  24. Здравствуйте.
    Что это за проводки такие в розовой изоляции? Вижу из повсюду, но только на фотках, на радиорынке не встречал :( Мне кто-то говорил, что они какие-то там специальные и дорогие очень, лапши навешали? Они как-то особо называются?

    1. Это МГТФ. Провод не дешевый (метр стоит около 10-15р), но очень мягкий, гибкий и прочный на излом (правда не в месте пайки, там ломается быстрей обычного т.к. ворсинки тонкие и их просто вырывает при жеской фиксации. Надо фиксировать отдельно чуть подаль от пайки, как у меня на фотке)

  25. здравствуйте, пытаюсь освоить AVR+LCD использую Atmega8 внутренний генератор 8Мгц, 8 проводов, дисплей WH1601L-YGH-CT[1] снял с принтера чеков, там работает, только иногда портит данные из CGRAM (выводит не то что записано) индикация нормальная.
    Извеняюсь за тупой вопрос, подобное тут уже было, но я не понял.
    вопщем пытаюсь вывести при помощи такого кода:
    .include «m8def.inc»
    .include «F:\AVR\Projects\LCD\LCD_macro.inc»
    .MACRO outi
    LDI R16,@1
    OUT @0,R16
    .ENDMACRO
    .ORG INT_VECTORS_SIZE
    Reset:
    OUTI spl,LOW(RAMEND)
    OUTI sph,HIGH(RAMEND)
    INIT_LCD
    LCDCLR

    WR_DATA ‘E’
    WR_DATA ‘B’
    WR_DATA 0xa1
    WR_DATA ‘E’
    WR_DATA ‘H’
    WR_DATA 0xa5
    WR_DATA 0xa6
    WR_DATA 0x20
    WR_DATA ‘E’
    WR_DATA ‘B’
    WR_DATA 0xa1
    WR_DATA ‘E’
    WR_DATA ‘H’
    WR_DATA 0xa5
    WR_DATA 0xa6
    Loop:
    RJMP Loop
    .include «F:\AVR\Projects\LCD\LCD.asm»
    ваводится только 8 разрядов, как остальное вывести?
    и еще после wr_data ставлю r20 предварительно записав данные при помощи ldi r20,0xa6
    чет не выводит. Помогите начинающему сдвинуться с мертвой точки.

    1. Он у тебя продолжает выводить, но в невидимую часть экрана. У твоего дисплея поди хитро разбит экран. Т.е. первые два символа на одной строке, вторые на другой (под строкой я имею ввиду тут строки видеопамяти)

      Тебе надо курсор сместить на нужное число позиций. Заюзай для этого спец макрос.

      А как выяснить куда? А это просто. Тупо гони в видеопамять аски коды от позиции 00 до тех пока вся видео память не заполнится (скажем по коду в секунду) скоро ты увидишь как у тебя начнет заполняться твои другие 8 символов.

      Ну или даташит погляди ;)

      1. спасибо за подсказку, индикатор какой то странный, он как двустрочный, но в одну строку, с первого адреса по восьмой отражает, потом до 40 нет после 40 по 48 опять в тоже место.
        поэкспериментировал с командой LCD_COORD Х,У, Выводит во вторую половину полько при значениях 40,2.
        Подскажите, а что эту команду только 1раз можно использовать?
        Сделал так:
        WR_DATA ‘E’
        WR_DATA ‘B’
        WR_DATA 0xa1
        WR_DATA ‘E’
        WR_DATA ‘H’
        lcd_coord 8,1
        WR_DATA ‘-‘
        lcd_coord 40,2
        WR_DATA ‘E’
        WR_DATA ‘B’
        WR_DATA 0xa1
        WR_DATA ‘E’
        WR_DATA ‘H’
        между 7 и 9 символом ни чего не появилось.
        И еще ткните, как мне данные из регистра на экран вывести, у вас написано использовать r17,
        делаю так: ldi r17,r20
        wr_data r17
        на экране ни чего, и ошибок нет.
        Может по электронке пообщаться, чтоб глупостями не засорять?

  26. Di, прошу прощения, если не в ту тему вопрос, но как-то сложно по сайту ориентироваться.
    Решил я немного разобраться с Си. Решил начать с подключения ЖКИ. У меня собрана макетная плата устройства. Есть там и ЖКИ. Причем все рабочее на 100%, т.к. на асме все прекрасно работает. Нашел несколько примеров простеньких программ. Но нихрена не работает. Единственное отличие у меня от взятых примеров — RS подключен к PD2, E к PD3, остальные же DB4, DB5, DB6, DB7 к старшим ьитам того же порта D. Ну так я RS, E и переопределил соответственно со своей схемой. Да, еще у меня индикатор не 2 строчный (как в примере) а 4 строчный по 20 знаков. Уже убиваю второй выходной — не могу понять, почему выдается какая-то белиберда на все строчки. Помнится мне с асмовским вариантом разобрался максимум за час. Вот что здесь не так? Если не трудно — взгляни навскидку.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    
    #include          //Библиотека ввода-вывода =4
    #define RS PD2    //Условное имя для сигнала RS (ЖКИ) =5   
    #define EN PD3     //Условное имя для сигнала E (ЖКИ) =6   
    #define TIME 2 //Задержки на 20 мкс при частоте 1 МГц =7
    //-------------Функция задержки времени-------------- =8
    void pause(unsigned int a) //"a" - длительность паузы =9
    { unsigned int cn;           //"c" - счетчик времени =10
      for (cn=a; cn > 0; cn--);  //Цикл задержки времени =11
    }                        //Окончание функции "pause" =12
    //---------Функция записи команды в ЖКИ------------- =13
    void lcd_com(unsigned char p)   //"p" - байт команды =14
    { PORTD &= ~_BV(RS);                       //Сигнал RS=0 =24
      PORTD |= _BV(EN);                        //Сигнал EN=1  =25
      PORTD &= 0x0F; PORTD |= (p & 0xF0);    //Старший ниббл =26
      pause(TIME);                 //Длительность сигнала EN =27
      //_delay_loop_2(3000);
      PORTD &= ~_BV(EN);   //EN=0, фронт записи команд в ЖКИ =28
      pause(TIME);                 //Длительность сигнала EN =29
      //_delay_loop_2(3000);
      PORTD |= _BV(EN);                        //Сигнал EN=1 =30
      PORTD &= 0x0F; PORTD |= (p << 4);      //Младший ниббл =31
     pause(TIME);                 //Длительность сигнала EN =32
      //_delay_loop_2(3000);
      PORTD &= ~_BV(EN);   //EN=0, фронт записи команд в ЖКИ =33
      pause(5*TIME);          //Пауза для выполнения команды =34
    }//_delay_loop_2(3000);  //Окончание функции "lcd_com" =35
    //---------Функция записи данных в ЖКИ-------------- =22
    void lcd_dat(unsigned char p)    //"p" - байт данных =23
    { PORTD |= _BV(RS) | _BV(EN);       //Сигналы RS=1, EN=1 =38
      PORTD &= 0x0F; PORTD |= (p & 0xF0);    //Старший ниббл =39
      pause(TIME);                 //Длительность сигнала EN =40
      PORTD &= ~_BV(EN);   //EN=0, фронт записи данных в ЖКИ =41
      pause(TIME);                 //Длительность сигнала EN =42
      PORTD |= _BV(EN);                        //Сигнал EN=1 =43
      PORTD &= 0x0F; PORTD |= (p << 4);      //Младший ниббл =44
      pause(TIME);                 //Длительность сигнала EN =45
      PORTD &= ~_BV(EN);   //EN=0, фронт записи данных в ЖКИ =46
      pause(5*TIME);          //Пауза для выполнения команды =47
    }                          //Окончание функции "lcd_dat" =48
    //---------Функция инициализации ЖКИ---------------- =30
    void lcd_init(void)   //Режим 8 бит, мигающий курсор =31
    { lcd_com(0x33);
     pause(500*TIME);           //Подготовка =51
      lcd_com(0x32); 
      lcd_com(0x28);        //4 бит, 2 строки =52
     lcd_com(0x08);             //Полное выключение дисплея =53
     lcd_com(0x01);
     pause(1000*TIME);     //Очистка дисплея =54
      lcd_com(0x06);                  //Сдвиг курсора вправо =55
      lcd_com(0x0D);    //Включение дисплея, мигающий курсор =56
    }                         //Окончание функции "lcd_init" =57
    //==============ОСНОВНАЯ ПРОГРАММА================== =40
    int main(void)      //Проверка знакогенератора 0-255 =41
    { unsigned char cifra=0, b;               //Счетчикм =42
      PORTB = DDRD = 0xFF; //В=входы с резист., D=выходы =42
      PORTC = 0xF8; DDRC = 0x07;  //PC0-3 выходы с лог.0 =43
      lcd_init();      //Инициализация ЖКИ (8 бит, 16х2) =44
      while (1)                       //Бесконечный цикл =45
    {	lcd_com(0x0C);      //Удаление видимости курсора =46
      lcd_com(0x86);    //Курсор на шестое слева место =47
      lcd_dat(cifra/100 + 0x30);               //Сотни =48
        lcd_dat((cifra/10)%10 + 0x30);         //Десятки =49
        lcd_dat(cifra%10 +0x30);               //Единицы =50
     lcd_dat('=');                    //Знак равенста =51
        lcd_dat(cifra);     //Содержимое знакогенератора =52
     for (b=0; b &lt; 10; b++) pause(25000); //Пауза 1 с =53
     lcd_com(0x80);    //Курсор на шестое слева место =54
     for (b=0; b< 5; b++) lcd_dat(' ');    //Очистка =55
     cifra++;      //Следующий символ знакогенератора =56
    		}           //Окончание функции "while" =57
    }       //WinAVR-20050214, длина HEX-кода 340 байтов =58

    Еще вопрос — в симуляторе AVRStudio паузы почему-то добавляют по времени какую-то ерунду — несколько микросекунд. И в этом примере и в другом тоже. Это симулятор их не понимает или они просто не работают??

  27. Спасибо за ответ. ))))) Пардон за иронию, это что же за компилятор такой умный, что жрет ТАКИЕ вещи???)))) Как же на нем что-то сделать можно? Может ему еще что по вкусу придется, прерывания например. В WinAwr оптимизация установлена — s -минимальная длина кода. Попробую изменить..

    1. Какие такие? Пустые циклы? Так это в порядке вещей. Оптимизатор вообще такой затейник…

      Порой целые куски кода выбрасывает. Знаешь какие только извраты приходится делать чтобы проверить какую нибудь функцию. Т.е. написал ты функцию, хочешь проверть по быстрому что она тебе выдает. Пишешь

      u08 i;

      i=myFunc(Y);
      Запускаешь под отладчиком, чтобы прям там поглядеть на выход в переменной i .. и получаешь облом. Т.к. i нигде дальше не участвует то оптимизатор взял и выбросил ее и функцию на которую идет отсыл. Приходится делать что то вроде
      UDR = myFunck(Y);
      такое уже не проигнорируешь.

      Поставь О0 и замени на стандартную задержку вида _delay_ms — она очень быстрая и компактная, т.к. на инлайновом ассемблере писана.

  28. Di, извини за тупые вопросы, но из мелочей и складывается картина. А при чем тут оптимизатор? Я же в симуляторе смотрю текст на Си, а не скомпилированый код. Это же, если я не ошибаюсь, как смотреть ассемблерный код до компиляции — чисто исходный текст.

    1. А он выполняется? Или ты его там только видишь? Если трассировать оптимизированный код по исходному тексту, то можно умом тронуться, т.к. ходит оно как то на так… =)

      Для просмотра ассемблерного результата там есть опция Toggle disassembler или как то так в меню View. Там же где watch, memory и прочие. Там будет ассемблерный код и его выполнение.

  29. К сожалению сайт больше не работает, чем работает.
    Ты был прав — оптимизация «съела» паузы. Индикатор заработал. Но с другой программой не работает, даже с учетом исправленых в первом случае косяков. ))) Си по отношению к асму навеял аналогию — можно неторопясь проехать сотню км на велосипеде (асм), а можно и на самолете (Си) — и быстрее и комфортнее. Только пока разберешься со всем этим самолетным
    управлением, всеми прибамбасами, человек на велике успеет не один раз обернуться туда-назад.)))
    Забавный этот Си.))) Сейчас отказывается работать простейшая кнопка со светодиодом..)))
    while (1)
    {
    if (bit_is_set(PINC,PC3)) PORTA |= _BV(PA3);
    else PORTA &= ~_BV(PA3);
    }

    1. Макросы bit_is_set ЕМНИП были упразднены в WinAVR начиная с какой то версии. _BV тоже рекомендую нахуй. Сегодня есть завтра нет.

      Попробуй такой расклад:

      1
      2
      3
      4
      5
      
      while (1)
      {
      if (PINC & 1<<PA3) PORTA |= 1<<PA3;
      else PORTA &=~(1<<PA3);
      }
  30. ))) ИМХО знаю. Буду знать теперь и ЕМНИП.))) Di, а тебе нельзя отослать кусок своей программы? Просто глянуть и навскидку сказать, много ли там баранины? Не в смысле логики работы, конечно, а в части правильности оформления что-ли? Я же так — по собственному наитию, может все не так совсем должно быть и выглядеть.

  31. А чем отличаются графические жидкокристаллические индикаторы от знакосинтезирующих жидкокристаллических индикаторов? Цена у них реально разная. Типа на графическом можно картинку нарисовать движущуюся, а на знакосинтезирующих только вывести цифры и буквы?

    1. Именно так. На знаковом только текст и 8 произвольных значков 8х8 пикселов. А на графическом у тебя поле их NxM точек и чо хошь там то и рисуй. Движущуюся, кстати, сложно будет сделать, они весьма тормозные.

    1. Там не все так просто. Дело в том, что у этих дисплеев кодировка не совпадает ни с одним из известных символьных кодировок. Поищи программу перекодировщик из ascii в 44780 на выходе у него абракадабра, вот ее и надо пихать в индикатор.

  32. DI HALT вопрос такой, в AVR Studio пробую разобраться с выводом информации на LCD с использованием твоих библиотек в макросе INIT_LCD в строчке

    WR_CMD (1<<LCD_CLR)

    программа у меня зависает регистр R16 изменяется, а регистр R17 нет 0х01.
    так как у меня на PinBoard стоит Mega32 я подключил файл m32def.inc, выставил 8 МГц, в чем моя ошибка.
    PS комментарии прочитал но — балалайка, то ли лыжи не едут, то ли я …..

  33. Привет, достал себе из одного девайса lcd дисплей, он по всем признакам с контроллером hd44780 или совместимым, проблема в том, что на него нет документации и вместо 14/16 пинов есть две площадки по 6 ножек, похоже на то чо он умеет передачу данных только по 4 битной шине.
    С ним была схема управления (на pic16), с помощью мультиметра и источника питания нашёл питание подсветки, питание самого lcd дисплея и ножку контраста, итого неопознанными остались 7 ножек, хочется как-то узнать их назначениег, пока в голову пришла единственная идея, записать минимальную последовательность бит которые надо пихать в порт чтобы увидеть реакцию в случаи правильной инициализации, и выводить её в порт раз за разом меняя комбинацию ножек на которые она выводится.
    Основная проблема в том что это 5040 перестановок, если каждая инициализация по нажатию кнопки то это около двух часов сидеть тыкать и смотреть (не говоря уже о том что надо как-то генерить последовательности сигналов. Если заранее записать, то получается около 35 килобайт, где их взять — не понятно).
    Собственно вопрос, есть идеи как узнать какой пин за что отвечает? )

  34. У меня такая проблема: есть функция, которая считывает флаг занятости ЖКИ BF, когда я её вставляю в функии записи данных или команд, на индикатор ничего не выводится (горит тоько верхняя строка чёрных квадратов), проверил напряжение на DB7 там около 5 вольт, когда её комменчу — всё работает отлично. Не могу понять, что я не так делаю при опросе флага.
    static inline void LCD_Wait(void)
    {
    unsigned char d;
    DDR_DATA = 0;
    PORT_DATA = 0xff;
    ClearBit(PORT_SIG, RS);
    SetBit(PORT_SIG, RW);
    do
    {
    SetBit(PORT_SIG, E);
    _delay_ms(2);
    ClearBit(PORT_SIG, E);
    d = PIN_DATA;
    }
    while(d & (1<<PINB7));
    ClearBit(PORT_SIG, RW);
    DDR_DATA =0xFF;
    }

      1. У меня всё работет и без ожидания флага занятости. Хочу прочитать регистр команд (IR) и с помощью старшего прочитаннго бита BF, проверить работает у меня чтение из ЖКИ или нет. Использую PinBoard. Вижу, что где-то косяк, а где не знаю, не хочется оставлять не разобравшись.

      1. в wikipedia написано что да.
        в магазине лежат:
        MT-16S2H-2ylg (тот самый на KS0066U),
        DV 16400 (он на HD44780? но он дорогой — 880руб, к тому же 4*16 символа)
        mt 1286av5 (он дешевле, но неизвестно о нем ничего)
        Какой выбрать из перечисленных?

          1. Блин, плохо…
            хотя уже разобрался — mt 1286av5 графический (128*64) и поэтому к моему проекту не подойдет.
            Остается выбор между DV 16400 и MT-16S2H-2ylg, в котором побеждает MT-16S2H-2ylg.
            И ничего что на другом контроллере!
            А вы, Di Halt, если увидете в ближайшие 2 недели где-нибудь нифу про KS0066U, пришлите мне пожалуйста.

    1. Нужно сделать BCD преобразование. Данных. На входе один байт, на выходе два байта. В каждом байте тетрада содержит цифру от 0 до 16, т.е. если загоняешь в алгоритм 255(1111 1111) то на выходе будет 0х02 0х55
      Дальше берешь эти цифры-тетрады и прибавляешь к числу 0х30 (или какой там код нуля?) получаешь ASCII код нужной цифры. Его уже выводишь.

    2. Вот выдраный из одного моего проекта алгоритм:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      ;-----------------------------------------------
      ; HEX TO ASCII
      ;-----------------------------------------------
      ;I think, this was the smallest (only 10 words).
       
      ;input: R16 = 8 bit value 0 ... 255
      ;output: R18, R17, R16 = digits
      ;bytes: 20
       
      Hex2Ascii:   LDI r18,-1+'0'
      _bcd1:      INC r18
               SUBI r16,100
               BRCC _bcd1
               LDI r17,10+'0'
      _bcd2:      DEC r17
               SUBI r16,-10
               BRCS _bcd2
               SBCI r16,-'0'
               RET
  35. DI привет. Не совсем понял:
    1. Чтение команды. Вообще какие команды то нужно из LCD читать? Проверка флага занятости это ясно. Чтение данных тоже. Кстати функция чтение флага, такая же как чтение команды.
    2.Перед тем как установить Е в 0. У тебя есть пуза. Она обязательна? Видел в других кодах нет такой паузы. Вот например с сайта http://www.mymcu.ru/Articles/Atmel17.htm:
    //ввод данных в LCD
    data_IN:
    swap r25 ;подготовить старшую тетраду для передачи
    mov r26,r25
    ori r26,$f0 ;установка бита 4 порта D (сигнал RS=1) и
    out portd,r26 ;бита 5 порта D ( сигнал E=1)

    cbi portd,5 ;стробирующий сброс бита 5 порта D ( сигнал E=0)

    swap r25 ;подготовить младшую тетраду для передачи
    mov r26,r25
    ori r26,$f0 ;установка бита 4 порта D (сигнал RS=1) и
    out portd,r26 ;бита 5 порта D ( сигнал E=1)

    cbi portd,5 ; стробирующий сброс бита 5 порта D ( сигнал E=0)
    ret

    1. 1. Чтение команды это флаг занятости. Ну еще, наверное, текущий режим может выдать.

      2. Без нее может дисплей не успеть среагировать. Запусти тот пример с сайта mymcu на частоте камня под 20мгц — боюсь нифига работать не будет.

      1. Под 20 может и не будет. Но у меня 8 мгц. И еще, у тебя в библиотеке для LCD всегда одна и таже задержка 10 тактов на 8 мгц.Это 1 микросекунда где-то, даже 2 учитывая rcall и ret. ты ее везде пихаеш. Хотя минимальная к lcd требуется 40 мкс на выполнение и чтение команд/данных. И вроде ж как то работает lcd?

  36. …уважаемые спецы подскажите как подключить этот жки к мк… если вообще возможно…
    [URL=http://www.radikal.ru][IMG]http://s002.radikal.ru/i198/1101/ef/f8dc14db04f0.jpg[/IMG][/URL]
    [URL=http://www.radikal.ru][IMG]http://s61.radikal.ru/i174/1101/76/dce4b5c9547b.jpg[/IMG][/URL]

  37. у меня странная проблема с экраном WH1602… включаю девайс, все ок, данные показывает без ошибок и пропусков. пара выкл-вкл, все ок. но потом может начаться чтото невообразимое, экран либо перестает выдавать данные, либо выдает чтото совсем не то что ожидалось. и продолжаться такое может следующие десяток-другой выкл-вкл.
    вроде как наводки, но ведь в тех же условиях он включается и нормально отображает данные.
    я прямо и не знаю что делать.

          1. Греться не должна. Но там иногда бывает генератор отрицательного напряжения и вот если его закоротить (а это не сложно, т.к. в этом случае распиновка не совпадает — например на 15-16 контакте минус напряжение и что то еще не то с контрастом) то можно получить прогрев микросхемы инвертора. Но опять же это не контроллер. А микросхема в соик8 рядом с контроллером.
            А может он на 3.3 вольта?

            1. Я прозванивал контакты все прям от ног меги328, все пучком, и по питалову все вроде ок
              пробывал и 4 вольта подавать, сейчас от ЮСБ питается вообще, экану не хватает напряжения этого (4 вольта) так-как тускло светить подсветка начинает и контраст падает

              Греется микруха под обозначением U1 она самая нажористая так которая поменьше U2 холодная

  38. DI, мне кажется у тебя совершенно неправильно проверяется флаг занятости. Судя по каментам и по гуглу, я далеко не первый, у кого флаг занятости горит всю жизнь без перерывов на обед.
    Проштудировав диаграму в даташите, вкралось мне подозрение, что проверять считывать флаг занятости надо когда E высоко. В твоём же коде Е ложится на землю и следующим же тактом считывается флаг занятости. Работает это потому что контроллер дофига быстрее чем HD44780 и успевает считать старое значение порта ещё до того как электроны добегут до экрана. Но стоит людям понизить частоту — и бах. Начинаются советы типа плюнуть на флаг и ждать время с запасом.
    На реальном экране не проверял, но в протеусе флаг занятости и счётчик адреса считывается ТОЛЬКО когда E высоко.

    1. Ты про диаграмму 15 из даташита на HD44780? Так если по ней смотреть, то там и DATA читается типо как бы по верхнему уровню. Только тут рулят не уровни, это не и2с, тут главное фронты. HD44780 щелкает на спадающем фронте E. На четвертой диаграмме того же даташита уже четко видно, что BF проверяется на фронте. Ну, а протеус это то еще глюкало. Там не только HD44780 странно себя ведеть, но и i2c в AVR работает некорректно и много чего еще. Я года два снес его нахер и с тех пор даже желания поставить не было. Вживую все работает. Перепробвал уже множество типов дисплеев, в разных режимах подключения — все всегда работало. Правда инициализации у всех разные бывают. Есть дисплеи которым надо потупить несколько мс после подачи питания и они даже флаг не выставляют. Есть те которые команды с первого раза не понимают (по крайней мере первые команды) надо по три раза подряд повторять.

  39. Data delay time tDDR 360ns
    Data hold time tDHR 5ns это из даташит HD44780U (LCD-II)

    Это говорит о том, что после Е=1 данные на шине гарантировано появляются через 360ns.
    И после Е=0 данные гарантировано будут присутствовать на шине 5ns. Выходит читать busy flag надо при Е=1 через 360ns. Если считывать флаг, когда Е станет равным 0, то при «медленных» МК флаг busy может правильно и не прочитаться.

      1. Суть такая, что есть обработка по прерыванию init0 с частотою несколько раз в секунду (5-6 раз). Во время обработки на экран выводиться число 009 но если увеличить частоту по прерыванию, то будет типа 0099 или 0090 ну и так далее 0090099. Тайменги увеличивал уменьшал, флаг BF проверяю, даже запрет на прерывание ставил вовремя вывода %).
        Atmega64 и sc1602 (ks0066)

  40. Может кто подскажет правильную распиновку выводов дисплея WH-0802A,по даташиту что то мудрённо обозначили и я не пойму,то ли змейкой порядок идёт или зигзагом.Я сделал скришнот с даташита и обозначил для удобства ответа выводы побуквенно.Вот скрин: http://s003.radikal.ru/i201/1103/f5/08247829993f.jpg и если нужен даташит вот ссылка на pdf http://www.platan.ru/pdf/datasheets/winstar/WH-0802A.pdf .Подскажете?

          1. Понятно,спасибо за подсказку!И ещё я хотел спросить,там отверстия двухсторонние(пятаки),и при рассмотрений вроде бы и металлизированные.Пайку тогда двухсторонюю делать или с одной стороны достаточно?Просто есть неудобство при сборке на плату,то есть жк крепится напрямую к плате через сквозные отверстия.

  41. Подключил и я дисплей Raystar RC1602A (на базе HD44780) 16 символов и две строки. Сначала подключил в Proteus — заработало. Потом припаял вживую. Подправил контрасность, питание, отключил программатор — работает. Прошивал программатором Громова(пять проводков) через программу avrdude под Linux. Использовал переходник usb-rs232 (vievcon), но долго пришивает. Буду пробовать usb программатор паять.

  42. А кто-нибудь подскажет какой-нибудь транзистор, чтобы подсветкой управлять (мне на форуме лень тему заводить)?
    В смысле, я в руках ничего кроме КТ315 и BC547 не держал особо. Они скорее всего подсветку не потянут, у 20×2 она должна жрать миллиампер 200.
    Так вот, вопрос: что есть из транзисторов (импортных) совсем для ламеров — чтобы купить штук 10, и их хватило и на подсветку (в том числе и ШИМ или вкл/выкл) и релюшками пощёлкать (скажем, напряжение до 30 вольт, ток до 1А). У меня в поделках напряжение питания обычно +5V от сети (в смысле мощности — завались, какая-то экономия по току не нужна), для реле — +12.
    Я тут всё то про полевики читаю, то ещё про что. Так чего купить-то можно? Чего щас современное? Чтобы как настоящий ламер: купил, впаял и не париться :)
    Про ULN2003 знаю, но тут не этот случай, видимо?

      1. О! Спасибо! А не-SMDшное чего-нибудь можно? Я всё ещё как старикан, DIP и обычные выводные паяю…
        Да, и второй вопрос — сейчас полевики также как совковые статики боятся? То-есть ножки надо фольгой заматывать, как раньше? Или можно бросить в пластиковую кассетницу и пусть валяются?

  43. Уважаемый DI HALT! Уважаемые друзья! Обращаюсь к Вам «за вспоможением»!!! У меня проблема-разбит дисплей на LEXICON PCM81. В нём стоит родной FUTABA M202SD01H. Его найти оказалось невозможным по всему миру. Наши фирмы, торгующие дисплеями написали мне, что он снят с производства и посоветовали мне взять его аналог FUTABA M202SD01LA. Но и его нигде не могу найти. Вопрос: можете что-нибудь подсказать по замене этого дисплея на другой? Я согласен на любой другой-пусть он даже не подходит по размеру (я как-нибудь приспособлю его). Пусть он будет ЖК. Пусть он будет стоять отдельно или ещё как-то, не важно. Мне сейчас важно что бы мой LEXICON PCM81 заработал! Помогите пожалуйста советом или если кто-то может оживить мой прибор! Готов подвезти его куда угодно (и естественно заплатить за работу)!!! На всякий случай мой телефон 8-903-629-04-60 Виталий.

  44. LCD WH1602B — отправка 4 бита происходит сразу после ввода старшей тетрады, а младшая тетрада заносится в половину следующего символа.
    Как вносить целый байт чтобы вывод символов не начиналсся после первых 4 бит? отсюда несоответсвие кодировке из даташита и первый глюченный символ.
    В даташите указан контроллер ks0066 или аналог? Вот это меня пугает, ks0066 по даташиту инициализировал, а вот как там осуществляется отправка данных я не понял, взял за основу у HD44780.

    void Lcd_write_data(uint8_t data)
    {
    Init_pin_out();
    rw_0;
    e_1;
    Delay_ms(3);
    rs_1;
    GPIO_Write(port,((data>>4)<<lcd_shift)); // старшая тетрада
    e_0;rs_1;
    Delay_ms(3);
    e_1;
    Delay_ms(3);
    rs_1;
    GPIO_Write(port,((data&0x0F)<<lcd_shift));// младшая тетрада
    e_0;

    }

    void Init_lcd()
    {
    Init_pin_out();

    Delay_ms(30);
    Lcd_write_cmd(Function_set);
    Delay_ms(39);

    Lcd_write_cmd(Display_on_off_control);
    Delay_ms(39);

    Lcd_write_cmd(Display_clear);
    Delay_ms(2);

    Lcd_write_cmd(Entry_mode_set);
    Delay_ms(10);

    }

  45. Помогите с контрастом!
    Я работал сначала на 16-02 символьным дисплеем, при этом резистор ставил 1кОм.
    Потом потребовалось 40-02. Поставил 1 кОм, покрутил, нету символов вообще, поставил на 10кОм на самом максимальном значении сопротивления — еле-еле видно пиксели. Поставил еще больше тоже не пашет. HELP!

    1. Скорей всего ты купил дисплей которому нужен отрицательный потенциал. Такие дисплеи лучше видно на морозе, но в целом с ними геморой. Контраст там включается на потенциометр не от нуля до Vcc, а примерно от -1.5 вольт до Vcc. Попробуй подать небольшое отрицательное напряжение на контраст (хотя бы с минуса батарейки подключенной плюсом на GND). Если поможет, значит оно. Ну или расшифруй маркировку дисплея по даташитам.

      Отрицательное напряжение можно сдернуть с MAX232 если оно на плате твоей есть. Ну или генератор отрицательного напряжения поставить.

    1. Это не даташит нифига. А так, отмазка. После маркировки у тебя стоит еще дофига букв. Вот по ним надо искать что это за конкретно модель. Там видов 10-15 существует.

      1. Там они отличаются только цветами и углом обзора.
        Я вот только на сайте одном нашел упоминание о том, что типы кристаллов у дисплеев разные.
        Вот каким я пользовался вначале, когда все работало:
        http://www.voltmaster.ru/cgi-bin/qwery.pl?id=987914670&group=21103
        Потом купил такой:
        http://www.voltmaster.ru/cgi-bin/qwery.pl?id=373119296&group=21103
        А когда поискал, нашел этот, он полностью идентичен первому, только больше знаков в нем:
        http://www.voltmaster.ru/cgi-bin/qwery.pl?id=498275704&group=21103

    1. Все, проверил работает действительно на отрицательном.
      Пришлось купить другой, но и в нем проблема оказалась! Fuuuuu.
      Короче, помогите.
      Вроде дисплей не сделан до конца, дорожки от контактов не идут в начинку дисплея.
      Гляньте. http://i067.radikal.ru/1202/b8/4d73c3c89a98.jpg

      1. Дорожки там идут на другую сторону, а потом возвращаются обратно. Видишь от сопли тоже дорожки в дырки идут. Так что тут все ок. Ищи правильный дисплей, не требующий негативных источников.

        YYH-CTK
        YGK-CTK
        например

          1. Ну а почему тогда не работает?
            Я же говорю, подключаю старый — все работает, подключаю этот — пусто, только контраст работает (вот от контраста видно, что контакты в начинку уходят)

            1. Понятия не имею. Может дисплей дохлый ,может инициализация кривая. А плата там двух, а то и трехслойная. Если дорожки уходят в плату, то это не значит что они оборваны, просто они идут на внутренний слой или на другую сторону платы.

  46. Здравствуйте, DI HALT. Давненько сижу на вашем сайте и с удовольствием читаю ваши, и не только материалы. Понимаю, что вы очень заняты, но хотелось бы задать вам вопрос. Недавно прикупил дисплей ACM2004D-FL-YBH-02 на вышеописанном контроллере с разрешением 20 х 4 символа. К дисплею нашел небольшую инструкцию. Судя по блок-схеме http://floomby.ru/content/doms3zDt0q там 16 строк на 200столбиков ячеек регистров памяти, то есть 400 кБ. Я верно понял? И еще я бы хотел узнать, как использовать русский алфавит? В даташите не нашел русские буквы, хотя у поставщика дисплей фигурирует как русско-английский. Вот ссылка на поставщика http://chip-nn.ru/72.php. Сорри, что без тегов, не привык к этим вещам.

    1. Там проще, там по биту на пиксель. Но вам эта память ни к чему. Т.к. это все в ведении контроллера и вам от этого ни холодно ни жарко. Все что у вас есть — экранный буфер на те самые 20х4 символа. И таблица знакогенератора которую менять нельзя. Т.е. есть там русский или нет зависит от конретной модели дисплея.

      Русский алфавит, если он там есть, то просто занимает другие коды в таблице знакогенератора. Коды не совпадают ни с одной из комповых кодировок потому ищити программу перекодировщик (ну или ручками ручками). Их как грязи.

  47. Понятно, спасибо. Печально, что DDRAM всего в 80 ячеек, надеялся что больше (могли-бы и 240 уместить). Значит и дисплей сдвигать некуда в моем случае? Если, как вы сказали, коды стандарта ASCII, то воспользуюсь вордовскими таблицами «вставить символ», там код показывается =)

    Ваш текст:
    «N — число строк. 0 — одна строка, 1 — две строки.»
    Если одна строка, то DDRAM можно представить как массив с одной строкой, который и будет отображаться на дисплее в одну строчку? В даташите для 4х20 точно такая-же команда:
    Sets data bus length (DL), # of display
    lines (N), and character fonts (F).
    DL=1: 8 bits F=0: 5×7 dots
    DL=0: 4 bits F=1: 5×10 dots
    N=0: 1 line display
    N=1: 2 lines display
    У дисплея то 4 строки, видать кусок документации общий с 2 строчными дисплеями.

    1. Не, там есть куда сдвигать. Там буфер больше чем окно. Правда точно не помню насколько. И вообще енмип в 20х4 там два контроллера по 20х2.

      Коды ascii только для английской таблицы. Для русской там своя кодировка, вроде как даже частично перекрывающаяся с английской (например русская С и английская С имееют один код символа, хотя я не уверен в этом на 100%) Так что из ворда не поможет :)

        1. Подпаял smd-резисторы на дисплей для подтяжки питания подсветки к общему питанию. Контрастность также подтянул через подстроечник на 10к. к питанию. Подключил питание дисплея для проверки. Контрастность регулируется. Измерил напряжение на выводах данных показывает 5V DB5. Есть вероятность, что я ее убил, когда коряво подрубал :-( Выводы DB0-DB7 не имеют в едь подтяжки до 5V?

          1. Все успешно инициализировал (сделал мигающий черный квадрат в ячейке DDRAM 01h). Дисплей рабочий, сделал режим отоброжения в 4 строки. Чтобы вывести слово, к примеру «World», я так понял нудно делать так после инициализации? :
            1)команда «адрес 00h» в DDRAM (RS=0)
            2)данные «символ W» из CGROM (RS=1)
            3)команда «адрес 01h» в DDRAM (RS=0)
            4)данные «символ o» из CGROM (RS=1)
            5)команда «адрес 02h» в DDRAM (RS=0)
            6)данные «символ r» из CGROM (RS=1)
            7)команда «адрес 03h» в DDRAM (RS=0)
            8)данные «символ l» из CGROM (RS=1)
            9)команда «адрес 04h» в DDRAM (RS=0)
            10)данные «символ d» из CGROM (RS=1)

            1. Нет, зачем так сложно. Главное выставить начальный адрес, а дальше писать только байты с буквами. Счетчиком адреса он сам будет переключать на новый адрес.

    1. Полностью разобрался с дисплеем. Displaytronic ACM2004D-FL-YBH-02 на 3 микрсхемах построен.
      Очень укуренная адресация:
      0x80 — 1 строчка 1 символ
      0x94 — 3 строчка 1 символ
      0xA8 — 2 строчка 1 символ
      0xBC -4 строчка 1 символ
      Адресация приведена с единицей в 7 бите данных (DB7=1 команда адресации)
      Получается, что сдвига экрана здесь нету. С русским шрифтом отлично работает.

  48. Пытаюсь написать на Pinboard2 программку для вывода на LCD символов. Есть такая программка, которая почему то не пашет — http://narod.ru/disk/53535325001.69c4f49e4f95f8ed99d6d47024500f59/LCD.asm.html . Выводит лишь черные квадратики. Не могли бы знающие люди глянуть и сказать в чем косяк?

  49. Привет! У меня есть ЖК дисплей, который я когда-то, где-то раздобыл… короче хрен пойми кто он такой! От него отходит 8ми контактный шлейф! Может кто знает распиновку и протокол обмена данным с такими дисплеями? На плате дисплея написано VTM88571A

  50. На заметку: есть некоторые дисплеи, которые никак не хотят работать от 3В (низкий контраст — возможно, хотят более 3В на пин контраста при 3в питании?), а некоторые китайские работают от 3В с одной строкой нормально, а с двумя — уже не работают. HJ1602A к примеру. И значение напряжения на выводе контраста должно быть разным для 1 и 2 строк — иначе либо не видно строк в 2-строчном режиме, либо в 1-строчном знакоместа подсвечиваются… Этот прикол сегодня стал причиной длительных и бессмысленных разбирательств с кодом. Хорошо, был другой ЖК, с одинаковым контрастом независимо от кол-ва строк…

      1. О_о сам DI HALT мне ответил!!! Вы кумир моей электронно — студенческой молодости! Я благодаря Вашим статьям диплом получил! ))
        А простым сдвигом экрана никак нельзя обойтись? Т.е я в цикле буду писать текст в память, и установлю бит S/C, что бы двигался экран, так не прокатит?

          1. Я вот немножко не врубился еще, а сдвиг курсора или экрана, это мы один раз проинициализировали, что сдвигаться экран будет и при поступлении нового символа он сдвигается? Или нам вручную после записи каждого символа нужно писать эту команду?

  51. Хочу поделиться парой знатных граблей, может кому пригодятся :)
    Задача была освоить работу в WinAVR с индикатором подключенным по схеме DFRobot LCD Keypad Shield, т.е. RW=0 на землю для экономии порта, соответственно готовность прочитать не можем, только выдерживать паузу. Данные 4-разрядные. Подключение к PB0-2 и PD4-7.
    Скачал 3 готовые библиотеки, в т.ч. из проекта работы Ethernet от lifelover. Поправил привязку, запустил — ни один пример не заработал, гонят мусор на экран и все.
    Запустил имитацию в AVR Studio+Hapsim — все работает на ура. А на реальной железке никак.
    Полдня мучился, вроде протокол простой, все выдается правильно, либы вроде как использовали, а не работает. Пока не догадался заглянуть в либу для Arduino.
    Оказывается, время выполнения команды «00000001 Очистка экрана» порядка 2000мкс, тогда как остальные команды (за исключением инициализации) укладываются в 37мкс. И если такую паузу не выждать, а прислать HD44780 еще что-то, то у него сносит крышу и дальше показывает только мусор.
    Авторы библиотек видимо либо читали готовность, либо не использовали очистку, либо пауза где-то снаружи образовывалась.
    Ну и в Hapsim модель индикатора наверно несколько упрощена.

  52. Здравствуйте! Вопрос:
    проектирую устройство которое должно выводить
    измеряемое значение на жк дисплей hd44780
    на дисплей будет выводится статическая информация
    и динамическая которая будет меняться по результатам.
    Как правильно обновлять дисплей, все сразу,
    или только что будет меняться, с каким интервалом??

  53. Всем привет, собрал такую схемку в протеусе, пишу

    INIT_LCD ; инициализация
    WR_CMD 0b00000001 ; отчистка экрана
    WR_CMD 0b00010100 ; сдвигаем курсор вправо
    WR_DATA 0b00110001 ; выводим цифру 1

    Не работает
    Вот принскрин
    http://s6.hostingkartinok.com/uploads/images/2014/01/fa76451dac94c7f01346388809e7a9c2.png

    Вот ссылка на проект
    http://yadi.sk/d/6e-SFDoaGeLTb

      1. Будет!!! в протеусе работать, если сделать так:

        Это опрос Флага занятости LCD!!! (чтение)

        Надо:
        Установить Е в 1
        подождать…
        Считать данные ЛСД
        Установить Е в 0
        ——————————————————
        SBI CMD_PORT,E (1)
        RCALL LCD_Delay
        IN R19,DATA_PIN Данные (так в протеусе работает)
        CBI CMD_PORT,E (0)

        А почему именно так работает? Да потому что так в даташите написано!
        ——————————————————
        ——————————————————

        А вот DI HALT, твой код:
        BusyWait: ;LCD_PORT_IN
        CBI CMD_PORT,RS
        SBI CMD_PORT,RW
        BusyLoop: SBI CMD_PORT,E (1)

        RCALL LCD_Delay

        CBI CMD_PORT,E (0)

        IN R16,DATA_PIN Данные (вот так в протеусе не работает)
        ANDI R16,0x80

        BRNE BusyLoop
        RET
        ——————————————————

          1. Вот. Но ведь то что тут указано реально работает. У меня проблем в протеусе нету.

            А твой вариант в протеусе не работает. И ты хочешь сказать, что в протеусе работает потому что я не правильно строб дергаю на чтении??? Я же говорю, Если сделать Е=1 Е=0 перед считыванием, то в протеусе вообще ничего не работает.

                1. В смысле врут? Это синхронная система работающая по стробам. Вот в этом промежутке:

                  читать нельзя. Т.к. данные там меняются. Это явно показано. После броска строба идет защелкивание данных и вот их уже можно читать. Сразу после строба.

                  1. А зачем тогда две диаграммы?
                    На диаграмме записи, говорится о том что верные данные будут в момент спада строба.
                    А на диаграмме чтения, говорится о том что верные данные будут считываться не в момент спада строба, а до него.
                    Иначе была бы одна диаграмма, на запись и чтение.
                    Ты отказываешься от своих слов?:
                    Чтение Данных
                    1. Ожидание готовности
                    2. Порт данных на вход с подтяжкой (DDR=0, PORT=1)
                    3. RS=1 (Данные)
                    4. RW=1 (чтение)
                    5. Е = 1 (Готовьсь! В этот момент данные из LCD вылазят на шину)
                    6. Пауза
                    7. Считываем данные с порта
                    8. E=0 (Ать!)
                    ———————————————————
                    Ведь считывание флага занятости, и есть чтение данных. Мы же его считываем. По этому и получается. Чтение не после Е1 Е0, а до спада строба.
                    И не стоит удалять мои сообщения. Тут я смотрю многие с этим сталкивались, в непонятии в чем же дело, как же так.
                    Итог:
                    Чтение!
                    Е = 1 (Готовьсь! В этот момент данные из LCD вылазят на шину)
                    Пауза
                    Считываем данные с порта
                    E=0 (Ать!)
                    ———————-
                    Ну дык я же об этом то и говорил!! А ты уже отказываешься.

                    1. А вот запись можно делать в двух вариантах:
                      1)в момент до спада строба
                      Е1
                      данные (но записаны они будут в момент спада)
                      Е0
                      ————
                      2)и в сам момент спада
                      Е1
                      Е0
                      данные (тоесть мы можем успеть записать пока Строб не упал в Полный ноль)
                      —————
                      Мы то ему сказали опустится, а он то не успел, и вот в этот момент еще можно записать.

                    2. А вот с записью не выйдет. Данные должны стоять уже на шине в момент падения Е, чтобы защелкнулись.

                    3. А вот время перехода строба из 1 в 0
                      Enable Rise/Fall Time tEr, tEf 25 nS
                      Мы сказали Е0 и у нас есть еще 25 nS успеть дать данные. Ну это если постараться

                    4. Да, с «записью» я облажал. Но все равно два варианта. Поправляю себя.
                      Вариант 1:
                      1. Е1
                      2. Данные или Команда
                      3. Е0
                      —————
                      Вариант 2:
                      1. Данные или Команда
                      2. Е1
                      3. Е0
                      —————
                      Проверил, работает.

                    5. Захотели нарисовать две вот и нарисовали. Они же разные, одна на запись, другая на чтение. Везде свои времянки расписаны. Они разные для каждого случая. То что формы похожие это ни разу не показатель.

                      «А на диаграмме чтения, говорится о том что верные данные будут считываться не в момент спада строба, а до него.»

                      С какой это стати? Там указано лишь то, что с момента поднятия Е за время Tddr (Data Delay Time) на шину будет выставлены данные. А вот после падения Е идет уже время Tdhr (Data Hold Time) время удержания их на шине, за которые их надо успеть считать. В это время уже гарантированно на шине валидные данные которые можно забирать. Причем минимальное время холда 5 чего то там (нс вроде бы), а вот максимального времени нет — т.к. до следующего дрыга строба они не меняются. И их можно хоть учитаться, ничего с ними не будет. Тогда как после поднятия Е чуть пролетел с временем выдержки и считал какое то левое говно в момент вывода данных.

                      «Ты отказываешься от своих слов?:»
                      Да, это у меня там ошибка. Т.к. алгоритм писался с чей то колхозной сишной либы, а не с даташита. Читать надо в статике, на времени T Hold, там нет никаких зависимостей от выдержек те данные на шине или не те… Там все статично. Строб прошел, данные вышли, а дальше не торопясь их читаем. Надо как нибудь поправить.

                      А я твои сообщения и не удаляю. Точнее только те где ты ссылки на одну и ту же картинку по 100500 раз дублируешь. Не надо так. Тэги у меня тут не работают, никакие. Особенно бб. С чего вы вообще берете что тут работают ББ тэги? Ладно там хтмл, но ББ?

                    6. «А на диаграмме чтения, говорится о том что верные данные будут считываться не в момент спада строба, а до него.»
                      Я не до выразился. Имел ввиду что чтения начинается еще до падения строба, и вплоть до полного спада строба в полный ноль.

                      Да, изначально тема пошла, что как бы в протеусе не должно работать. Ну а причина то, не правильное чтение Флага занятости. Я пытался сказать в чем причина. А ты сказал что я не правильно делаю. Ну а в итоге то правильно. Да и протеус же согласен. Чтение флага должно быть таким же как и обычное чтение.

                      Про ББ http://forum.easyelectronics.ru/faq.php?sid=702a8a5d8c2930d3e4d5c16b9c86c9a3#f4r3

                    7. У блога и форума совершенно разные движки. Тут же даже регистрация раздельная и разные аккаунты. Соответственно ББ не работают (да и нигде они кроме форумов больше и не работают) А внизу окна ввода расписаны допустимые тэги. Там чистый хтмл.

                    8. DI, помоги. Скажи как на LCD вывести многозначное число? (Калькулятор).
                      Вариант есть, но уверен что так это не делается.
                      А делал так:
                      Имею я ответ калькулятора 234(лежит в памяти). И что бы их загнать в LCD, я этот ответ делю на 10, получаю 23 и (4) в раздельности, далее 23 делю на 10, получаю (2) и (3) в раздельности. А потом я их по одной отправляю на LCD.
                      Но деление то я делаю на Асме и это очень неудобно, при том условии что мой алгоритм не знает скольки значное будет число. Приходится заранее указывать на сколько знаков нужно разложить число.

                      Так может есть какой то другой вариант? Какая то фишка..

                    9. Да нет никаких хитростей там. Просто делишь сначала на сотни, потом на десятки и так далее. Нули можешь отображать, а можешь нет. Можно не тратиться на затратное деление, а хлопать двоичное число по маскам и определять общий размер тупо по его двоичной длине и дальше уже разлагать на составные части исходя из этого.

  54. Здрастуйте.Есть вот у меня 1 вопрос…Собрал я кароче электронную плату на микроконтролере атмега8а и всё вроде работает а вот экран не показывает инфу и естественно немогу вводить данные с кнопок.В чем может быть проблема? в микроконтролере или же неправильно соеденил экран?

  55. Попался мне в руки дисплей, внешне похожий на описываемый. На котором написано P110 и ниже TW-22 94V-0, и ещё ниже Data Vision (видимо, фирма) У нему припаивается 14-проводнорй шлейф. На микросхеме маркировки нет. Поиски в гугл результатов пока не дали. Может кому либо попадался этот зверь?

    1. Экспериментальным путем установлено, что это 1х16 дисплей со стандартной разводкой и очень похожей системой команд. По крайней мере слово Hellow он вывел, а вот в слове word были несколько крокодябликов . Без даташита трудно понять, в чем дело.

      1. Скорей он и есть. Попробуй таймингами поиграть. Ну и кодовую таблиц просечь. Возможно все там ок просто таблица нестандартная. Выведи все символы от 0 до 255 и посмотри что там да как.

  56. Привет Di Halt. Решил я тут написать свою либу для работы с дисплеем, с преферансом и мадемуазель, разумеется, на Algorithm Builder’e. Ничего, как ты понимаешь, не заработало (твой пример в RTOS работает, у меня PB-II). Я скачал доку на дисплей и внимательно прочел её, и возникли вопросы:
    1. Твоя инициализация. Для инициализации дисплея ты используешь функцию WR_CMD, которая мало того что использует Busy_Wait, хотя до инициализации этот флаг не работает, она еще и шлёт байт полностью — т.е. сначала старшую тетраду, потом младшую, хотя до перехода в 4-бит режим нужно слать только старшую тетраду.
    2. Сами данные в инициализации — ты сразу шлёшь запрос о переходе в 4-битный режим, хотя дока говорит, что сначала нужно сказать что ты хочешь работать в 8-битном режиме, а уже потом, когда инициализация закончится, запросить 4-битный режим.
    3.Не понятно, как работает строб. По Восходящему фронту или спадающему? В доке не нашел этого. А у тебя иногда мы отсылаем данные после E=0, а, например, при чтении мы ставим E=1 и читаем, а потом уже E=0 (что пояснено как «Ать!»).
    Кусок доки
    Мой алгоритм
    Объявления к нему.

      1. А с кодом не поможешь?) А то у меня не работает не как ты делал, не как производитель завещал. Повторюсь, в RTOS дисплей работает, значит, я просто не могу повторить ритуал. Самое большое, чего я добился — пропали квадратики с дисплея (видимо, выключился, хотя я этого не хотел), это произошло при инициализации по методу производителя. Я уже не знаю что делать, чес слово :(

        1. Разобрался наконец — дело было в том, что в этом же проекте я подключал матричную клавиатуру через внешние прерывания (INT0-2) и когда начал работать с дисплеем — отключил её, а инициализацию прерываний убрать забыл, и вышло что у меня прерывания INT0-2 включены, а порт в высокоимпедансном состоянии и ловит помехи, так МК и уходил в бесконечную обработку этих прерываний. Так то. Еще кстати была проблема, она меня не сильно задержала, но я её так и не решил, обошел просто — почему то, хоть я и вношу единицу в JTD (JTAG disable), порт С всёравно не хочет работать — всё в режиме приёма с включенной подтяжкой (не весь, там некоторые ноги, JTAGовские). Как это исправить? Это тока в фузах наверное отключается?

  57. Привет Di!
    Уже несколько дней мучаюсь с экраном, не получается вообще вывести на него ничего!
    Я использую Си, Пинбоард 2.
    Подскажи, пожалуйста :)
    Вот мой код:

    static void writeCommand(unsigned char command)
    {
    CBI(LCD_SIG_PORT, LCD_RW);
    CBI(LCD_SIG_PORT, LCD_RS);
    SBI(LCD_SIG_PORT, LCD_E);
    LCD_DATA_PORT = command;
    _delay_us(39);
    CBI(LCD_SIG_PORT, LCD_E);
    }

    void initLCD8b(void)
    {
    // set all pins to out
    LCD_DATA_DDR = 0xFF;
    // set signal pins to out
    LCD_SIG_DDR |= SFT(LCD_RS) | SFT(LCD_RW) | SFT(LCD_E);

    // initialisation
    _delay_ms(15);
    // step 1
    // make it not via writeCommand because large delay
    CBI(LCD_SIG_PORT, LCD_RW);
    CBI(LCD_SIG_PORT, LCD_RS);
    SBI(LCD_SIG_PORT, LCD_E);
    LCD_DATA_PORT = 0b00110000;
    _delay_ms(5);
    CBI(LCD_SIG_PORT, LCD_E);
    // step 2
    // make it not via writeCommand because large delay
    CBI(LCD_SIG_PORT, LCD_RW);
    CBI(LCD_SIG_PORT, LCD_RS);
    SBI(LCD_SIG_PORT, LCD_E);
    LCD_DATA_PORT = 0b00110000;
    _delay_us(100);
    CBI(LCD_SIG_PORT, LCD_E);
    // step 3
    writeCommand(0b00110000);
    // DataLength:8-bit
    // numbers of display line (N:2-line/1-line)
    // display font type (F:5x11 dots/5x8 dots)
    writeCommand(0b00111000);
    // Set display (D), cursor (C ), and blinking of cursor (B) on/off control bit.
    writeCommand(0b00001100);
    // clear display
    writeCommand(0b00000001);
    // Entery mode set
    writeCommand(0b00000100);
    }

    void writeCharToLCD(const unsigned char c)
    {
    CBI(LCD_SIG_PORT, LCD_RW);
    SBI(LCD_SIG_PORT, LCD_RS);
    SBI(LCD_SIG_PORT, LCD_E);
    LCD_DATA_PORT = c;
    _delay_us(43);
    CBI(LCD_SIG_PORT, LCD_E);
    }

    void writeStrToLCD(const unsigned char* str, const unsigned char size)
    {
    for (const unsigned char* end = str + size; str < end; ++str)
    {
    writeCharToLCD(*str);
    }
    }

    int main(void)
    {
    initLCD8b();
    writeStrToLCD((unsigned char*)"Hello yo!!!", 11);
    _delay_ms(3000);

    while (1)
    {
    writeStrToLCD((unsigned char*)"t6 mazafaka!", 12);
    _delay_ms(5000);
    }

    return 0;
    }

    Заранее спасибо!

    1. Сам с собой тут общаюсь =)
      Ну, другим, может, полезно будет :)

      Заставил я дисплей работать. Выводит, что хочу.
      Решил это заменой порта LCD_DATA_PORT.
      Раньше я его определил как PORTC — не работало. Поменял на PORTB — заработало.

      Почему так?
      В PB2 есть какая особенность для PORTC? Может там какие-то помехи?

  58. Уважаемый Di Halt. Нужна помощь, я с такими индикаторами практически не сталкивался, а тут возникла проблемка. На рабочем приборе треснул индикатор C20416B (часть символов не индицируется ), купил в китае C2004A физически подходит один к одному, но при подключении засвечиваются все сегменты. Что можно или что нужно сделать?

    1. Контрастность покрути. У тебя она на максимум выкручена. А еще она может по полярности не совпадать. Эти индикаторы отличаются весьма большим разнообразием схем вклчюения контраста, порой им даже надо отрицательное напряжение давать.

      1. Спасибо что откликнулся. Контрастность крутить нечем ,пришлось в разрыв цепи контрастности впаивать переменник 10к и тем самым выкрутив еще 7,5 кОм контрастность уменьшилась и символы стали видны. Но появилась другая проблема, вместо некоторых букв кириллицы – какие-то другие ASCII символы. Можно ли это победить и как ?

        1. А вот это уже все. Если в дисплее кириллицы нет, то это уже никак не исправить. Она там жестко зашита. Ищи такой же дисплей. но с кириллицей. И да, в Китае его скорей всего не купишь, там таких просто нет. Покупать надо тут.

        2. Но есть шанс из двух дисплеев собрать один. Стекла у них обычно идентичные и можно попробовать стекло одного пересадить в другой. Разбираются они элементарно.

          1. Попытался поменять стекла местами но увы пока не получилось, вроде все одинаково, а символы некоторые толстые некоторые усеченные с разных сторон, вернул обратно на свои места – символы полноценные. Понять не могу- почему??????

  59. У меня вопрос.

    Алгоритм чтения флага занятости:
    E=1 (Готовьсь!!!)
    Пауза (14 тактов процессора на 8МГЦ хватало)
    Е=0 (Пли!)
    Читаем из порта.

    Алгоритм чтения команды:
    Е = 1 (Готовьсь! В этот момент данные из LCD вылазят на шину)
    Пауза
    Считываем данные с порта
    E=0 (Ать!)

    Почему в первом случае порт читаем ПОСЛЕ окончания строба, а во втором ДО?

    Полагаю, что оба варианта рабочие, но все таки — как надо делать по феншую?

    1. Меня этот вопрос тоже интересует…
      Думаю, что правильнее алгоритм «чтение команды».
      Сегодня на железе (WH1604a+mega32) проверил следующий алгоритм чтения флага занятости BF:
      RS=0
      R/W=1
      E=1
      и в цикле (не дергая E) ожидал сброса флага BF
      M0: sbic PINC, BF
      rjmp M0
      Все сработало на ура…

    2. Проверял логику с JTAG ICE mk II- при установке E=1 дисплей выдает данные на шину, при Е=0 шина переходит в третье состояние. Следовательно сначала выставляем единицу потом читаем и только потом сбрасываем. Таким образом и проверка в цикле также работоспособна.

  60. здрасивуйте уважаемый DI HALT
    я всегда с удовольствием читаю ваши статьи и хотя они написаны очень доходчиво но всеравно не всегда все понятно
    и вынужден задавать вопрос.
    Для изучения я подключил ко всем значащим ножкам LCD переключатели и хочу последовательно передать команды и данные по вашей схеме.
    Мне нужно уточнить ,смогу ли я таким образом симмитировать работу LCD? и чтобы отправить байты в LCD для этого нужно каждый раз заземлить вывод E (т.е простробировать) или как то по другому нужно ввести?
    Заранее благодарен.

  61. У меня есть вопрос по поводу прерываний. У меня часы тикают по прерыванию. И выходит что мне уже ни где нельзя запрещать прерывания. Иначе часы пропустят счет и будут вечно опаздывать. Работают на внутреннем генераторе. Часы работают на матрице 8х8 на 7ми сегментном и на HD44780. А хотелось бы много чего добавить в МК, но если буду запрещать прерывания то кранты часам. Что делать? Брать отдельный МК для часов? Там где ты указывал запрет прерываний в передаче команды или данных для HD44780, мне пришлось отключить.

  62. Вот это «Подсветка хавает примерно 100мА и поэтому нужно выставить туда токоограничительный резистор на 100 Ом» выглядит странно. При питании 5В ток через резистор будет 50мА, а с учетом падения на самой подсветке и того меньше. Лучше так: «Для оптимального тока подсветки (20-30 мА) … резистор 100+-20 Ом …»

  63. Здравствуйте. Помогите опознать жк и его подключение. На лицевой стороне дисплей 86 / 24 мм в металлическом прижимном креплении и цифра (1) — отсчет контактов шлейфа. Плата 95 / 30 мм и 15 припаянных отводов. На обратной стороне надписи “97-24288-0″ ,” LM311L” на наклейке, а под ней “LM105L”, и “JAPAN”. микрухи – M5259( OKI JAPAN ) – 2 шт. HD44780A00 (JAPAN) – 1 шт. ??? С какими контроллерами совместим?

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