Теория по КМПУ Готовые элементы систем Технологии и хитрости Прочее Магазин Контакты
 

Знакосинтезирующий ЖКИ 1602 и клавиатура: экономим выводы микроконтроллера


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

Введение

Третьего дня одному моему хорошему знакомому заказали поделку. Задача была поставлена чисто на уровне программирования – взять готовые шылды для ардуины и из них сляпать требуемый дывайс. На вопрос: «А зачем именно Ардуино?» был получен стандартный ответ: «Для Ардуины есть много готовых шылдов, и к тому же они все оптимизированы по максимуму». Сразу скажу – я не являюсь ардуино-ненавистником. Более того – я целиком поддерживаю платформу, освоение которой вполне доступно даже для школьников (благо как базовый контроллер, так и всевозможные шылды к нему из дружественного Китая сто́ят буквально гроши). Но, однако, я не могу молчать, когда рядом со мной толкуют о какой-то мега-оптимизации модулей для Ардуино, ибо примеров их кривизны (как софтовой, так и чисто конструктивной) – просто го́ры.

Добил меня рассказ о том, как всё мега-оптимизировано в ЖКИ-шылде с кнопками («LCD 1602 Shield»):



На первый взгляд, там и правда царит оптимизация: для управления индикатором используется шесть, а не семь (как обычно «принято») линий МК, а для опроса пяти кнопок – всего одна аналоговая линия A0. Итого, вместо «стандартных» 7+5=12 линий МК шылдом ЖКИ заюзано лишь 6+1=7 линий. И вот это преподносится как охуенный «прорыв» в оптимизации (при этом, как ни изгаляйся, данный шылд в при́нципе нельзя прикрутить к камням, не имеющими на своем борту АЦП – например, кирпичи ATMega8515 тихо сосут в углу). Однако, на данный «прорыв» у меня есть кой-чего возразить. А начнем, как обычно, от печки.

Оптимизация подключения индикатора

Для начала рассмотрим, насколько вообще можно сократить количество линий управления индикатором (здесь речь пока идет именно об индикаторе, а не о кнопках). Как известно, все знакоситезирующие ЖКИ могут работать как в 4-х битном режиме обмена данными, так и в 8-ми битном (если кто не в курсе – гуглите фразу «мт-16s2d», там в даташыте всё по-русски объясняется). Для 8-ми битного обмена требуется максимум 11 управляющих выводов микроконтроллера:

Вывод ЖКИ Направление Назначение и описание
RS Вход Адресный сигнал: выбор между передачей данных (High) и команд управления (Low)
R/W Вход Выбор режима записи (Low) или чтения (High)
E Вход Разрешение обращений к индикатору (а также строб данных)
DB0 Вход/выход Шина данных (8-ми битный режим) (младший бит в 8-ми битном режиме)
DB1 Вход/выход Шина данных (8-ми битный режим)
DB2 Вход/выход Шина данных (8-ми битный режим)
DB3 Вход/выход Шина данных (8-ми битный режим)
DB4 Вход/выход Шина данных (8-ми и 4-х битные режимы) (младший бит в 4-х битном режиме)
DB5 Вход/выход Шина данных (8-ми и 4-х битные режимы)
DB6 Вход/выход Шина данных (8-ми и 4-х битные режимы)
DB7 Вход/выход Шина данных (8-ми и 4-х битные режимы) (старший бит)

А вот для 4-х битного – всего лишь семь: «R/W», «RS», «E», «DB7», «DB6», «DB5», «DB4» (т.е. в данном режиме работы линии «DB3»-«DB0» не используются). При этом бонус 8-ми битного режима состоит только в том, что данные на ЖКИ будут отображаться несколько быстрее, чем при 4-х битном режиме. Ну а поскольку жидкий индикатор сам по себе далеко не быстродействующее устройство, то как-то так исторически повелось, что для экономии выводов МК все используют 4-х битный режим обмена данными с ЖКИ. Итого примем, что для управления индикатором нам надо максимум 7 линий микроконтроллера, т.е. на данном этапе экономия составила 4 вывода от максимально возможного. Отметим, что шылд «LCD1602» использует именно 4-х битный интерфейс общения с ЖКИ, так что тут к нему никаких претензий быть не может.

Оптимизируем дальше – рассматриваемые индикаторы могут как принимать данные, так и выдавать их наружу. Например, они могут рассказать камню, в какой позиции в данный момент находится курсор, и какой символ в этой позиции записан. Плюс при помощи функций чтения данных можно считать флаг занятости ЖКИ, что позволяет несколько сократить время вывода символов на экран. За тип обмена инфой (чтение/запись) отвечает вывод «R/W» ЖКИ – если на этом выводе присутствует логическая единица, то производится чтение данных с индикатора, а если логический нуль, то данные в индикатор записываются. Т.е. в теории можно организовать полномасштабное общение с ЖКИ, однако, в реальной жизни чтение какой-либо информации из индикатора не используется – гораздо проще организовать процесс общения с ЖКИ на тупых задержках, а на флаг занятости попросту забить (тем более, такой подход вполне разрешается и документацией на ЖК-модуль). Ну, а где какой символ на экране нарисован – мы, в принципе, и сами в курсе, ибо эти символы в ЖКИ именно нами и были записаны. Таким образом, управлять выводом «R/W», по большому счету, не нужно – достаточно его просто заземлить, при этом индикатор будет работать только в режиме записи (вывода на экран) данных, а большего обычно от него и не требуется. И здесь мы можем сэкономить еще один вывод МК. Отметим, что в шылде «LCD1602» данная экономия присутствует (хотя лично я обычно даю пользователю возможность как тупо заземлить вывод «R/W», так и подключить его к какому-либо выводу МК – чисто на всякий случай). Таким образом, с точки зрения управления индикатором рассматриваемый шылд и впрямь оптимизирован по максимуму.

Кривое подключение кнопок

А вот насчет кнопок управления индикатором в шылде «LCD1602» не всё так радужно. Будем откровенны – опрос их состояния здесь сделан совсем уж по-дурацки. Вкратце реализованный подход можно описать так – АЦП должно постоянно пасти́ уровень сигнала на выводе A0 (вход ADC0 для камней ATMegaX8), и в зависимости от этого уровня понимать, какая кнопка была нажата (и была ли нажата вообще).

В данном подходе я вижу сразу два изъяна. Первый изъян – использование АЦП для считывания состояния кнопок, что чаще всего будет отжирать ресурсы камня впустую. Ну а кирпичи, не имеющие модуля АЦП на борту (ATMega8515, AT90USB162 и т.д.), и вовсе курят в сторонке, ибо для управления ЖКИ тупо рожей не вышли (тут, правда, к Ардуине вопросов нет – у всех используемых ею камней АЦП в наличии). А второй изъян логически вытекает из первого – раз задействуется АЦП, то нужно использовать лишний вывод МК для считывания информации от кнопок. С одной стороны, всего один дополнительный вывод камня – не так уж и много, но с другой – чтобы считать сигналы от пяти кнопок в данном случае совершенно необязательно вообще прибегать к помощи АЦП. Соответственно, задействовать дополнительный вывод МК (ADC0) тоже не надо. И вот про то, как объединить сигналы управления ЖКИ вместе с сигналами от кнопок, и будет рассказано далее.

Правильное подключение кнопок

Итак, примем как данность – в своих устройствах радиолюбители (да и профессиональные разработчики) часто прибегают к использованию знакосинтезирующих ЖКИ. При этом данные индикаторы зачастую призваны не только отображать какую-либо полезную «текущую» информацию (режим работы устройства, текущее значение параметров и т.д.), но и участвовать в настройке дывайса непосредственно с передней панели. Естественно, для навигации по меню и установки требуемых значений параметров нужны управляющие кнопки (в общем случае: «МЕНЮ/ВЫБОР», «ВВЕРХ», «ВНИЗ», «+» и «-»). Данный раздел показывает, каким образом может быть осуществлено подключение к микроконтроллеру вышеупомянутых кнопок без задействования дополнительных аппаратных ресурсов камня.

Как было сказано ранее, в большинстве случаев от жидкого индикатора требуется только вывод необходимой информации на экран. Поэтому пин «R/W» ЖКИ мы можем тупо заземлить. Плюс ко всему, работать в 8-ми битном режиме чаще всего совсем неинтересно и даже расточительно. В итоге основным режимом работы ЖКИ (который мы и рассмотрим далее) в большинстве случаев будет «4 бита + только запись» (в смысле – только запись данных в индикатор). Поэтому для управления индикатором нам потребуется всего 6 линий микроконтроллера: «E», «RS», «DB7», «DB6», «DB5», «DB4» (см. выше). Запомним – именно 6 линий. Далее нам нужно вспомнить, что шина обмена данными с индикатором является стробируемой. Это означает, что пока на линии «Е» не будет сформирован задний фронт импульса (хотя, возможно, существуют разновидности ЖКИ, стробируемые по переднему фронту), индикатору совершенно плевать, что́ происходит на других его линиях данных. Иными словами, пока не будет выставлен нужный строб на линии «Е», мы можем творить что угодно – соответствующие данные в ЖКИ всё равно не запишутся. А это означает вот что – мы можем подключить к линиям «RS», «DB7», «DB6», «DB5», «DB4» вышеупомянутые кнопки (естественно, названия кнопок даны условно; в реальности они могут иметь какой угодно функционал) и дрочить их как нам заблагорассудится, пока не нужно будет записать что-либо в ЖКИ. Никакого влияния на информацию, отображаемую на ЖКИ, это дрочительство не окажет, а вот считать состояние кнопок камнем мы вполне сможем («стандартный» опрос входа в то время, когда на ЖКИ ничего отсылать не надо). Ну а когда нам понадобится вывести что-то новое на индикатор, мы просто выдадим на линии «RS», «DB7», «DB6», «DB5», «DB4» нужный код и дадим строб на линию «Е».

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

Общая схема

В общем, есть у нас микроконтроллер. Есть у нас знакосинтезирующий ЖКИ, на котором надо отображать какие-либо данные. Также у нас есть довольно разветвленное меню, в котором мы можем устанавливать различные параметры работы устройства (также отображаемые на экране индикатора). И есть у нас заказчик, которому вот кровь из носа надо удешевить поделку. Последнее означает одно – количество выводов камня заведомо будет сокращено до минимально возможной величины, т.е. лишних пинов для кнопок управления устройством нам, скорее всего, просто не дадут.

Для связи с индикатором в данном случае наиболее бюджетно будет построить вот такую схему (сразу включив сюда и кнопки управления устройством):



Обратите внимание на то, что, как и было оговорено ранее, индикатор работает в режиме «только запись» (т.е. в него можно только записывать информацию), поскольку вывод R/W у него заземлен. Камень ATMega8, как и названия портов, к которым подключен индикатор и кнопки, взят просто для примера. Для других вариантов кирпичей тут важно лишь два момента:

•  соответствующие порты МК (PD1, PD7-PD4) должны уметь работать и как входы, и как выходы;

•  порты камня, к которым подключаются кнопки, при работе в качестве входов должны иметь внутреннюю подтяжку к плюсу питания. Если в микроконтроллере на аппаратном уровне данная фича отсутствует, необходимо будет реализовать подобные подтяжки внешне.

Принцип работы предлагаемой схемы (ра́вно как и алгоритм программы) достаточно прост. Для опроса состояния кнопок выводы PD1, PD7-PD4 МК должны быть настроены на вход и подтянуты к плюсу питания резисторами (вывод PD0 лучше всегда делать выходом, и в те моменты времени, когда общения с индикатором нет, на нем должен присутствовать логический нуль). Данный опрос кнопок является «традиционным», т.е. камень, например, просто поочередно проверяет сигнал на цифровых входах PD1, PD7-PD4 (можно также прикрутить сюда прерывания – вариантов реализации опроса масса). Поскольку эти входы подтянуты к плюсу, ненажатому состоянию кнопки будет соответствовать логическая единица, а нажатому – логический нуль (при обработке сигналов от кнопок не забываем о «дребезге» их контактов). А поскольку строб для ЖКИ (линия «Е») отсутствует, всё, что происходит на линиях «RS» и «DB7»-«DB4» индикатором игнорируется, т.е. различный мусор, соответствующий разным комбинациям нажатых/ненажатых кнопок, просто проходит мимо ЖК-модуля. Отметим, что т.к. ЖКИ работает в режиме «только запись», линии его управления «DB7»-«DB4» являются входами, поэтому никакого влияния на выводы PD7-PD4 микроконтроллера оказывать не будут.

Как только появляется необходимость пообщаться с ЖКИ, линии PD1, PD7-PD4 камня должны быть переведены на выход. Далее на этих линиях выставляется код, соответствующий передаваемой в индикатор информации, и даются стробы по линии «Е», т.е. производится обычная запись данных в ЖКИ по 4-х битной шине. Отметим, что код, выставляемый камнем на выходах PD1, PD7-PD4 не может быть «испорчен» кнопками. Если кнопка не нажата, то на соответствующий выход МК не оказывается никакого влияния (т.е. на нем будет именно то значение, которое мы выставили). А если кнопка нажата, то по этому выходу просто потечет дополнительный ток, значение которого будет ограничено за счет резисторов R1-R5, при этом состояние выхода тоже не изменится. Таким образом, получаем, что с одной стороны информация в индикатор будет передана верно, а с другой – выходы PD1, PD7-PD4 микроконтроллера заведомо не сгорят даже в том случае, когда соответствующая кнопка (или кнопки) будут нажаты. Ну а после передачи данных в ЖКИ нужно снова перевести выводы PD1, PD7-PD4 на вход и подтянуть их к плюсу питания для последующего опроса состояния кнопок.

Номиналы резисторов R1-R5

Отдельно нужно сказать о номиналах резисторов R1-R5. Как было отмечено ранее, основная их задача – ограничить ток вывода микроконтроллера в тот момент, когда:

•  вывод камня является выходом;

•  на выводе МК установлена логическая единица;

•  кнопка, подключенная к выводу, нажата (например, для вывода PD6 это будет кнопка SB3).

Если бы кнопка была подключена к выводу камня напрямую, то в описанной выше ситуации с данным выводом пришлось бы попрощаться – он бы тупо сгорел из-за превышения максимально допустимого тока (ибо на выходе у нас было бы КЗ). Отсюда следует минимально возможное сопротивление резисторов R1-R5 – оно должно быть достаточным для того, чтобы ток выхода при нажатой кнопке и выбранном напряжении питания МК не превысил максимально допустимого значения. Например, для камня ATMega8 это значение составляет 40мА, поэтому при питании +5,0В сопротивление резисторов R1-R5 не должно быть меньше 5,0В/40мА=125 Ом. Однако, просто так грузить выходы МК и жрать лишнюю энергию от источника было бы довольно странно. Поэтому в реальности сопротивление резисторов R1-R5 выбирается исходя из следующего.

Рассмотрим для определенности кнопку SB1, резистор R1 и вход камня PD1. Очевидно, что для уменьшения потребления электрической энергии при нажатии на кнопку нам надо увеличивать значение резистора R1. С другой стороны, как видно из схемы, при нажатии кнопки SB1 на входе PD1 камня образуется резистивный делитель, составленный из резистора R1 (нижнее плечо) и внутреннего резистора МК RPU, подтягивающего данный вход к плюсу питания (верхнее плечо):



И состояние кнопки, грубо говоря, «считывается» с резистора R1. А у любой цифровой микросхемы есть такой параметр, как «максимальное входное напряжение низкого уровня (VIL MAX)». Это напряжение, при превышении которого не гарантировано распознавание входного сигнала низкого уровня в качестве логического нуля. Применительно к нашему случаю: при неограниченном увеличении сопротивления резистора R1 напряжение на нем также будет увеличиваться. Поэтому может возникнуть ситуация, когда нажатая кнопка будет распознана как не нажатая. И, как нетрудно догадаться, сопротивление резисторов R1-R5 лучше всего выбирать именно исходя из этого факта: с одной стороны, оно должно быть как можно больше (для уменьшения дополнительного тока выхода МК), а с другой – должно гарантировать нормальное распознавание нажатого и не нажатого состояния кнопки.

В качестве примера посчитаем максимально допустимое сопротивление резисторов R1-R5 для камня ATMega8. Необходимые параметры микросхемы (берутся из даташыта):

•  VIL MAX = 0,2VCC;

•  RPU MIN = 20кОм.

Исходя из значения 0,2VCC, можем сделать вывод, что коэффициент деления делителя RPUR1 на входе PD1 микроконтроллера не может быть меньше

KD MIN = 1/0,2 = 5.

Ну и отсюда несложно определить сопротивление резистора R1, при превышении которого мы не сможем гарантировать нормального распознавания состояния кнопки SB1:

R1MAX = RPU MIN/( KD MIN–1) = 20кОм/(5-1) = 5кОм.

А в реальности (с учетом стандартных значений номиналов и допусков) наиболее доступными и дешевыми будут резисторы номиналом R1...R5 = 4,7кОм ± 5%. При этом максимально возможное их сопротивление не будет превышать 4,935кОм (105% от 4,7кОм), что вполне согласуется с вышеприведенными расчетами.

Заключение

Вот, в принципе, и вся «наука». Честно говоря, я не совсем понимаю, почему в широко распространенном шылде «LCD 1602» применен не рассмотренный принцип опроса кнопок, а АЦП-шный. Ведь в том включении, который реализован в шылде, в общем случае невозможно даже определить одновременное нажатие нескольких кнопок. Да и номиналы соответствующих резисторов разные, что с точки зрения массового изготовления не совсем корректно. В общем, одни вопросы к шылду «LCD 1602», да.

Отмечу, что рассмотренный принцип подключения кнопок (скорее всего) будет работать и в том случае, когда необходима не только запись информации в ЖКИ, но и считывание ее из индикатора. Сразу скажу, что лично я этот факт не проверял, однако по крайней мере в теории ему вроде как ничего не противоречит. Единственный неприятный момент тут может быть связан вот с чем. Как отмечалось выше, резисторы R1-R5 служат для того, чтобы защитить выходы микроконтроллера от выгорания при нажатии на кнопки (т.к. без резисторов там образуется тупое КЗ). Так вот, в случае чтения инфы с ЖКИ, выводы «DB7»-«DB4» индикатора станут выходами. Соответственно, в данном случае защищать от выгорания надо будет уже́ не камень, а ЖК-модуль. Фича в том, что максимально допустимый ток выводов «DB7»-«DB4» в режиме выходов напрямую не приводится ни в документации на сами индикаторы, ни в документации на микросхемы текстовых матричных контроллеров, используемых в ЖКИ (см., например, контроллеры ST7065C и ST7066U, используемые в дешевых китайских индикаторах 1602A-1). Данное значение можно прикинуть лишь косвенно из условий, для которых в таблицах приводятся напряжения логической единицы и нуля выходов контроллера, и составляет оно порядка 0,5мА. Соответственно, для защиты такого выхода при напряжении питания +5,0В нам понадобится резистор с сопротивлением не менее 5,0В/0,5мА=10кОм. Но если на стороне МК мы используем внутреннюю подтяжку к плюсу с минимальным значением 20кОм, то коэффициент деления цепочки, например, RPUR1 на входе PD1 будет равен 3. А в соответствии с вышеприведенными расчетами, он не может быть меньше 5, иначе правильное распознавание нажатости/ненажатости кнопки SB1 не гарантируется. Поэтому нам придется увеличивать сопротивление резистора, подтягивающего вход МК к плюсу питания. В принципе, это ничему не противоречит, следует только помнить, что внутренняя подтяжка камня здесь уже́ не прокатывает – нужно будет использовать внешние резисторы. К тому же, для управления линией «R/W» индикатора потребуется дополнительный вывод МК. Так что использовать «универсальное» общение с ЖКИ (т.е. как запись, так и чтение), на мой взгляд, следует только тогда, когда разрабатываемое устройство того действительно требует.

Ну и последнее. Бывает так, что для управления простеньким меню нам вполне будет достаточно и трех кнопок вместо пяти, а вот дополнительная светодиодная индикация (например, режимов работы устройства) не помешает. В этом случае, конечно, никто не запрещает взамен «ненужных» кнопок воткнуть светодиоды, уменьшив сопротивление соответствующих резисторов из числа R1-R5. Однако, лучше так не делать. Сгореть, конечно, в данном случае ничего не сгорит, но. Во время отправки инфы в индикатор те светодиоды, на которые будет подана логическая единица, начнут светиться. А если в другие моменты времени они не горят, то мы получим «паразитные» вспышки. Отмечу, что человеческий глаз легко замечает вспышки длительностью даже 60-70мкс на обычных «прозрачных» светодиодах. Ну а при управлении индикатором наиболее распространен случай, когда для формирования «длины посылки» используется не флаг занятости BF, а тупые задержки, при этом длительность вывода на экран одного символа в 4-х битном режиме составляет обычно не менее 74мкс. Таким образом, светодиоды в любом случае начнут случайным образом мигать тогда, когда от них этого не требуется, поэтому заменять кнопки светиками категорически не рекомендуется.

Ну а на сегодня всё. Желаю удачи при работе с ЖКИ и кнопками!

Обсудить эту заметку можно здесь



Место для разного (сдается)

 




Создание, "дизайн", содержание "сайта": podkassetnik
Для писем и газет: Почта России электрическая

Место для © (копирайта, понятно, нет, но ссылайтесь хотя бы на первоисточник)

Since 2013 и до наших дней