Вывод текста на 1602 LCD со скроллингом вверх
- Войдите на сайт для отправки комментариев
Уважаемые Гуру,
помогите, пожалуйста, модифицировать библиотеку LiquidCristalLCD_I2C , чтобы при заполнении последней строки, или при поступлении возврата каретки в последней строке, экран скроллился на одну строку вверх. Я знаю, что нужно организовать экранный буффер из своей программы, сделать промежуточный слой, который будет прорисовывать экран. такое я делал. Но у меня нет возможности менять саму программу. Нужно заставить библиотеку так себя вести.
Если честно, у меня нет нужных знаний по С++ и учить его мне нехочется-неможется. Но с-подобные языки для меня не являются совсем непонятными. Так, что, если дадите правильный пинок (в виде небольшого примера, как переопределить print и write в библиотеке) - я попробую удержать курс ;-).
Заранее спасибо ;-)
у меня нет нужных знаний по С++ и учить его мне нехочется-неможется.
Ну ведь ты сам все понял? ЧТО именно ты написал на хоббийном форуме?
Пока нахер не послали, иди уж лучше сам в раздел "Ищу исполнителя".
Уважаемый, я и сам послать могу, к сожалению. До сего момента на форумах такого ответа не встречал.
А по теме, я сделаю сам, но это будет долго. Может кто-то уже с таким связывался и имеет наработки.
Ну вот, как то так.
С наиглубочайшим уважением.
doleynikov, вообще-то wdrakula, прав. Задача простая, минут на 30-40. Но лично мне она без надобности и переспектив в ее использовании не вижу. Если есть желание потерпеть когда у меня или кого другого звезды сойдутся в охотку написать это - давайте пример использования и описание ожидаемого поведения класса.
Ну и кроме того, я бы не модифицировал библиотеку, а написал бы производный класс от LiquidCristalLCD_I2C
Я не сомневаюсь, что задача простая. Я делал такое не в виде библиотеки, а в виде набора функций в программе. Я, просто не совсем понимаю, как модифицировать библиотеку. Ну , если честно, совсем не понимаю, как переопределить print в библиотеке, чтобы он применял все особенности обычного print, но делал скроллинг при выводе.
Поведение ожидается примерно таким. По умолчанию, вывод начинается с начала нижней строки. По ее заполнении, в зависимости от какого-то флага, например установленного wrap=1, строка копируется в верхнюю и очищается. Последующий вывод опять в начала строки. Обрабатываются коды "\n" и "\r", то есть, сдвиг экрана без смещения текущей позиции и смещение текущей позиции курсора в начало строки. Даже без реакции на backspace и beep.
сейчас ищу более-менее понятный пример, так как с плюсами у меня нелады, а учить ради одной задачи - не хочется.
В любом случае, если я ненароком кого-то обидел - прошу меня простить, я не хотел сказать ничего обидного, так получилось и я сожалею об этом.
Ты никого не обидел.
Ты на хоббийном форуме написал, что тебе лень заниматься тем, чем тут увлекаются люди.
Переводится это таким образом, если ты, вдруг, настолько социально инфантилен, что не можешь предсказать реакцию людей:
"Я - занимаюсь делом, а Вы тут маятесь херней, на которую я свое драгоценное время тратить никак не могу.
Поскольку вам тут, по моему мнению, все равно, какой херней маяться, то напишите мне пару страниц кода."
===================================
Я напишу тебе, как нужно сделать, в надежде, что "лень заниматься" было сказано по инфантильной тупости подростка, который хочет быть "взрослым дядей", а не из чванства и пафоса.
Переопределить нужно единственную функцию write(). Она определена inline строчкой в начале cpp файла библиотеки.
Далее есть два способа, проще и сложнее.
1. проще, в функции write(), проверять на '\r' и '\n'. И переставлять курсор в первом случае, и читать нижнюю строку из памяти экрана с адреса 0x40 и писать ее с ардеса 0, в случае '\n'. Судя по произведенному впечатлению, чтение по и2с у тебя не получится. Может поймешь? Нужно так: сперва пишешь в регистр, что тебе нужно, а потом читаешь из него. Нужно хорощо понимать, как именно работает модуль и2с для 1602.
2. сложнее, но не нужно читать из экрана. При каждом сеткурсор и выводе отслеживать место и заполнять буфер нижней строки, которой завести в библиотеке, также завести координаты курсора (достаточно адрес в памяти)
Вот спасибо! Я не профессионал в электронике - просто ковыряюсь для своего удовольствия. Когда-то пытался искать, можно ли читать из i2c контроллера на 8574t или контроллера экрана 1602, но везде получал ответ, что у этих сущьностей читать память нельзя - только писать. Вот читать даташиты я тоже не умею, но, получается , нужно это. Попробую по Вашей рекомендации.
Вот, может кому пригодится! наконец нашел упоминание, что можно читать данные из дисплейной памяти таких дисплеев!
http://radiolaba.ru/microcotrollers/podklyuchenie-lcd-1602-po-i2c-interfeysu.html
Вывод - внимательнее читать, то что написано ;-)
Теперь буду пробовать что-то читать
учить его мне нехочется-неможется.
Ну, тогда придётся платить тому, кому в своё время хотелось и моглось.
Пробую читать видеопамать. Написал такое:
Все время выдает 255. Подозреваю, что где-то накосячил. Может поглядите профессиональным взором? Кстати, я слегка подправил библиотечку:
private методы вывел из private, так как не мог вызвать write4bits из своего расширения класса.
Почитайте статейки еще внимательней. В hd44780 еще есть так называемый busy flag, который нужно анализировать при проведении операций. А то я смотрю - прям без паузы начинаете сливать инфу с DDRAM. А между тем в табличке, что в статье по ссылке - паузы быть должны.
в табличке написано, что команда выполняется 43мкс, я сделал паузу в 1мс и ничего не поменялось. Наверное я косячу на более фендаментальном уровне.
ЗЫ: А режим я прнавильно задаю?
Wire.write((highnib) | 0B00000011); // установил Rs и Rw
LCD точно работает. Я вижу меняющиеся 'a' и 'w' в первой позиции первой строки.
А я бы настоятельно рекомендовал не свзываться с чтением из памяти дисплея, а не жалеть 80байт памяти и хранить дубль буффера дисплея в ОЗУ, перерисовывая дисплей из буфера при переходе со стороки на строку. Тогда и базовый класс не пришлось бы трогать в библиотеке.
Вижу только :
Никаких пауз после выставления адреса DDRAM не вижу.
Спасибо, я , в конце-концов так и сделаю. Но сейчас действительно интересно, как читать эти значения. Попробую разобраться.
прочитайте методы класса wire.
beginTransmission это передача, а чтение это requestFrom. Примеры есть в ИДЕ, в соотв. разделе.
важно понять, что вы совмещаете ДВА протокола:
1. 1602 и PCF8574.
По и2с вы работаете с 8574, которая - просто и2с регистр - расширитель портов входа/выхода, а поверх этого вы работаете с экраном.
Поэтому проще всего представить себе, что никакого и2с нет, и вы работаете с 8-и битным дополнительным портом.
поэтому выставляем на этом порту правильно комбинацию для чтения, а потом читаем нужное, на нужных ногах. Помним, что по 4 бита, у нас экран в 4-х битном режиме.
Вывод изменился. теперь всегда '3'
для начала - советую забыть про библиотку экрана совсем, потом к ней вернетесь, а взять в сети библиотеку чсто для 8574, так будет удобнее.
таким образом, перед кажым чтением состояния регистра, нужно выдать высокий Е, а потом низкий Е.
Проверено, что работает так: все, что нужно и высокий Е выставляем в записи. ждем 1 мс, выставляеи низкий Е, читаем. Если читам много байт, а нам нужно 16 байт прочесть, то потом делаем такой повтор:
- выставить высокий Е, делей(1), низкий Е, читаем сразу без делея. И так 32 раза. По 4 бита.
E это тактирование? я не вижу как управлять тактированием в библиотечках. Или я чего-то не понял?
да, чего-то не понял. Е - в библиотеке называется En в весьма кривой комбинации write4bits() , см. ниже, он используется в функции pulseEnable().
Можно очень упростить эту конструкцию. Тут на форуме была моя реализация софт и2с и 1602, там это немного изящнее сделано. Поищите на ветке про тиньку 13, может там... может я сам позже найду.
Спасибо за искреннее желание помочь. Вероятно я сильно бестолковый, однако.
Я сделаю по совету уважаемого Sr.FatCat и перехвачу вывод. тем более, что переходов по экрану не будет. Для скролла нужно будет хранить только текущую (нижнюю) строку. Вернее даже только видимую ее часть. Это мне понять проще. и библиотеку терзать не нужно будет, убирая private.
ЗЫ: как оказалось, библиотеку все равно терзать придется - в переопределяемом методе используется приватный метод. Поэтому проще вывести метод send из блока private.