Снова о мультиплексинге...

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

В одном устройстве применяю дешевенький дисплейчик 16*1 с совместимыми командами HD44780, подключенный в урезанном варианте — 4 линии данных. А поскольку большее время они (эти линии) простаивают, решил я их догрузить дополнительной задачей. Получилась вот такая схемка:


Для того, чтобы при нажатии кнопки не произошло короткого замыкания линий данных, подключены они последовательно с резисторами 2,2 килоома, которые при нормальной работе шине данных не мешают. А при опросе кнопок их номинал оказывается достаточно низким, чтобы МК определил соединение. Номинал этот выбран чисто интуитивно и выдержал испытания на «5».
В приложении процедура опроса в ассемблере AVR, расширение файла пришлось изменить для загрузки. Код достаточно, по-моему, прокомментирован и не должен доставить сложности в понимании.

;*****************************************************
	; Опрос 4-х кнопок без фильтрации дребезга / @ Fahivec
B_Scan:	; Кнопки подключены между линиями данных LCD. 39 команд

.def Button	= R15	; переменная сканирования кнопок
.equ D7 = 3		; Порт данных MCU бит 3 = Шина данных LCD бит D7
;.equ D6 = 2
.equ D5 = 1		; Порт данных MCU бит 1 = Шина данных LCD бит D5
;.equ D4 = 0
	Push Temp
	Push Temp1
	cbi CMD_PORT,RW ; LCD на запись = D4..В7 на вход (Hi-Z)
	rcall PortIn	; библиотека DI HALT'а LCD4.asm (PullUp=1). 7 команд
; Scan 1
	cbi DATA_PORT,D7	; LCD_D7=0
	sbi DATA_DDR,D7		; выход
	nop	; подождать пока линия будет действительно на "0"
	nop	; из-за паразитивных ёмкостей.
	nop	; при более высоких тактовых частотах добавить еще несколько NOP-ов!
	nop	; при меньших можно сократить.
	in Temp, DATA_PIN	; считать состояние
	ori Temp, 0xFA	    ; маска для битов 0,2 (1111.1x1x)
	sec		    ; Flag Carry для ROL
	rol Temp	    ; сместить в биты 1,3 (1111.x1x1)
	sbi DATA_PORT,D7	; PullUp
	cbi DATA_DDR,D7		; снова вход
; Scan 2
	cbi DATA_PORT,D5	; LCD_D5=0
	sbi DATA_DDR,D5		; выход
	nop
	nop
	nop
	nop
	in Temp1, DATA_PIN	; считать состояние
	ori Temp1, 0xFA	  ; маска для битов 0,2 (1111.1x1x)
	sbi DATA_PORT,D5	; PullUp
	cbi DATA_DDR,D5		; снова вход

	and Temp, Temp1	 ; объединить оба скана (1111.xxxx)
	COM Temp		; инвертировать (0000.XXXX) - если ни одна не нажата =0x00
	mov Button, Temp	; результат в переменную
	pop Temp1
	pop Temp
	ret			; 32+7=39 команд
;****************************************************

Кратко об алгоритме.
Выводим оба устройства (МК и ЖКИ) в состояние приема, при этом подтягиваем линии МК к плюсу (мой ЖКИ при переходе в режим записи делает это сам — имеем двойную подтяжку).
Затем в два прохода поочередно опускаем нечетные линии данных и считываем состояние всей шины. Подключенные резисторы при этом образуют с резисторами подтяжки делитель, соотношение которого достаточно для получения логического нуля от нажатой кнопки.
Соответственно «фильтруем» только две линии данных, причем результат первого «скана» сдвигаем на один бит влево, поскольку результатом считывания оказываются одни и теже биты. в конце объединяем оба опроса в один полубайт и получаем по одному инфо-биту для каждой кнопки, что дает отклик на нажатие нескольких одновременно.
Кнопке S1 соответствуе бит 0, S2 — бит 2, S3 — бит 1, S4 — бит 3.
В моем случае четко отслеживаются три одновременно нажатых (в различном сочетании) кнопки.
МК работает на частоте 10 мГц. Что за устройство — тема совершенно отдельная. Сам приборчик еще не доведен до «ума» — как програмно, так и в железе, поэтому здесь о нем ничего писать не буду.
В заключении хочу сказать, что кол-во кнопок наверняка можно увеличить, по крайней мере в схеме с 8-ю линиями данных. У меня же такой задачи не стояло.
Идею и код отдаю в общее некоммерческое пользование «как есть» без всяких гарантий :)

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

P.S. Не смог однозначно определиться куда публиковать: в «Схемотехнику» или в «Алгоритмы..», поэтому оставляю пока в личном блоге.
  • +3
  • 12 сентября 2012, 01:01
  • Fahivec
  • 1
Файлы в топике: B_Scan.txt

Комментарии (36)

RSS свернуть / развернуть
А первый вариант отсюда чем не подошёл?
0
0
АЦП уже занят своими процедурами и не хотел еще более их усложнять.
Кроме того там пишут об относительной ненадежности такого включения.
0
Практика показывает, что эта схема вполне себя оправдывает. Главный неустранимый минус — некорректное определение при множественном нажатии.
0
Это решается простым изменением схемы до классического ЦАП с весовыми резисторами.
+1
продемонстрируйте, если можно.
0
С удовольствием, но как картинку вставить?
Набросал в Excel табличку для восьми комбинаций из трех кнопок по схеме, приведенной ниже Lifelover , только без ОУ на выходе и с тактовыми кнопками. Без ОУ немного нелинейно получается, но зависимость явно пропорциональная.
0
В формочке написания коммента в тулбаре для этого кнопочки есть. Целых две!
0
  • avatar
  • Vga
  • 12 сентября 2012, 23:56
Спасибо, нашел. Сразу не заметил — моя вина. Исправлюсь :)
0
Как-то так:

0
Можно, но для этого нужны перекидные кнопачки (а тактовые кнопочки-то не перекидные) плюс как то фильтровать перепад в момент переключения)
0
Перекидные нужны для R-2R. А для ЦАП, где номиналы резисторов пропорциональны 2^n, нужны тактовые кнопочки. Разве не так?
0
Не так)

0
Впрочем, я туплю, и эта схема тоже. Перекидные кнопочки тут действительно не нужны -_-
0
А не проще было кнопки относительно земли включить, а не между парами линий?
Программа опроса гораздо проще. Да и сами соединения.
+5
  • avatar
  • SWG
  • 12 сентября 2012, 10:13
Чем же соединения проще? Если отказаться от последовательных с кнопками резисторов, то в момент нажатия кнопки линия данных окажется грубо на «земле», а вдруг тут обмен данными? А с ними соединения не проще, разве что разводка на плате.
Ну а процедура упростится без сомнения. А вот так у меня еще останется возможность увеличения числа кнопок (подключением к земле) про запас — ну это уже оправдание :) — не продумал, честно говоря.
0
Чем же соединения проще?
Тем, что вторые контакты всех кнопок тупо соединяются между собой и с землей. К тому же, резисторы, если они выводные, выполняют роль перемычек для подключения к шине. А иначе придется думать над отведением сигнала от шины к обоим концам кнопки, причем резистор обеспечит только один.
Хотя если тянуть шину к кнопкам после индикатора, то проблем, вероятно, не возникнет.
0
  • avatar
  • Vga
  • 12 сентября 2012, 12:43
Кнопки все равно нужны на передней панели. У меня они на отдельной узенькой платке поместились между ЖКИ-платой и панелью. Соединений от этой платки к самому ЖКИ-модулю всего четыре. А иначе пришлось бы тянуть еще и землю, хотя это и не существенно.
От ЖКИ к основной плате шлейф.
Не охота панель разкручивать, чтоб сфотать. Буду толкатели кнопок переделывать — сфотаю. Надеюсь, по описанию понятно.
0
Ну, обычно ЖК и кнопки находятся на одной передней панели, и вполне логично разместить их на одной печатной плате.
Но если плата отдельная и соединяется только с ЖК — что ж, вполне логичное решение.
0
  • avatar
  • Vga
  • 12 сентября 2012, 14:44
А разве не МК инициализируети этот «а вдруг»? Откуда ему взяться, если МК в этот момент кнопки опрашивает?
0
  • avatar
  • STT
  • 12 сентября 2012, 14:36
МК работает в цикле довольно шустро. После опроса кнопок идет обработка меню и выполнение соотв. функций. Так вот там-то и приходится выводить в дисплей, а кнопка еще не отжата. В этом устройстве, в отличие от Виндовса, реакция на нажатие, а не на отпускание.
0
Чем же соединения проще?
5 проводов вместо 8.
В программе — при опросе делаете все 4 линии входами с подтяжкой, и проверяете на 0. И нажатие нескольких кнопок одновременно — не проблема.

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

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

Если отказаться от последовательных с кнопками резисторов, то в момент нажатия кнопки линия данных окажется грубо на «земле», а вдруг тут обмен данными?
Зачем же отказываться? С ними удобнее разводка (особенно если выводные). А с резисторами — пофигу, в режиме вывода порт и индикатор их и не заметят.
0
  • avatar
  • SWG
  • 12 сентября 2012, 17:05
5 проводов вместо 8.
Это на предоставленной схеме восемь связей с шиной данных, на самом деле резисторы подключены непосредственно на плате к кнопкам, а от них идут всего 4 связи к соотв. линиям данных.
0
Гениально =)
0
Спасибо! Кто-то сказал «Гениальность граничит с безумием». Мне самому сложно судить, на какой стороне этой границы находится бОльшая часть вышепредложенного. :)
0


У нас в пульте используется вот такой вариант мультиплексинга, для опроса кнопок добавилась только линия PB0.
0
0
А можно нормальную картинку?
0
Как сюда вставить нормальную картинку так и не разобрался, поэтому вот ссылка на фоткохостинг:
s018.radikal.ru/i511/1209/47/3885dfa1bd49.jpg
Если будет что-то не понятно по алгоритму работы — спрашивайте.
0
Благодарствую. Ну в принципе понятно: когда нет передачи по шине данных — переводите ноги в Hi-Z и мониторите нажатия, а в режиме обмена выводы PUSH-PULL и потому им почти фиолетово, на сопротивление в 1к, если кнопка в этот момент нажата.
0
Видимо вы немного не так поняли, поэтому поясню принцип работы: На PD0-PD6 выводится лог.1, на PD7 лог. 0. Тогда, если кнопка нажата, на выводе PB0 будет напряжение 0,7В (падение на диоде). Это напряжение детектируется как лог.0 и обрабатывается контроллером. Если же кнопка не нажата, то на выводе PB0 — 5Вольт. Ну и провести подобные действия для каждой линии данных.

А когда по шине данных передаются команды для LCD-дисплея, то нажатие кнопок дейтсвительно фиолетово.
0
Зачем? Куда разумнее перевести линию данных в Pull-Up, линию опроса кнопок в 0 и считать значение шины. Одной командой получишь состояние всех кнопок одновременно. Диоды только перевернуть надо (либо, если позволяет МК — выставить шину в Pull-Down и выдать единицу на линию опроса).
На время передачи данных по шине линию опроса надо переводить в Hi-Z или в 1 (0 для варианта с pull-down).
0
  • avatar
  • Vga
  • 25 сентября 2012, 23:29
Куда разумнее перевести линию данных в Pull-Up
*линии данных. Или, точнее, шину.
0
  • avatar
  • Vga
  • 25 сентября 2012, 23:30
Встроенный Pull-Up слабенький, сколько граблей из-за него бывало. А пульт стоит в генераторе для индукционного нагрева мощностью 125кВт, там помех гуляет…
0
Ну, если в таких условиях — тогда да, проще поставить пулл-ап на линию опроса и опрашивать кнопки поочередно. Если только шина сама по себе не требует пуллапов.
0
  • avatar
  • Vga
  • 26 сентября 2012, 00:48
На черном фоне — нихрена не видать…
0
  • avatar
  • SWG
  • 13 сентября 2012, 14:44
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.