Arduino: модуль расширителя-мультиплексора CD74HC4067
Продолжаем тему модулей расширения портов для Arduino. Иногда возникает необходимость получать аналоговый сигнал с большого количества сенсоров, опрашивая их по очереди. Но у стандартной платы Arduino на контроллере ATMega328 всего 5 аналоговых входов.
В такой ситуации нас выручит аналоговый мультиплексор 1-в-16 CD74HC4067 (рис. 1). Он работает очень просто: в зависимости от логических уровней на входах адреса S0…S3 соединяет общий вывод Z c одним из выводов Y0…Y15. Двоичное значение адреса соответствует номеру вывода Y. Например, адрес 0000 подключает к выводу Z вывод Y0; адрес 0011 подключает вывод Y3.

Коммутация работает как обычная проволочная перемычка между выводом Z и одним из выводов Y: направление передачи сигнала не имеет значения, сигнал на входе полностью повторяет сигнал на выходе. Мультиплексор разработан для коммутации аналоговых сигналов, но с равным успехом он может коммутировать и логические уровни – “перемычке” между выводами нет разницы, какой сигнал пропускать через себя.
Разумеется, мультиплексор можно использовать не только для переключения источников сигнала на аналоговом входе Arduino, но и управлять при помощи микроконтроллера распространением аналоговых сигналов между блоками устройства. Например, коммутировать источники звукового сигнала в усилителе НЧ. Кстати, коэффициент нелинейных искажений синусоидального сигнала в канале коммутации составляет не более 0,015%.
Основные ограничения по параметрам сигнала:
- Уровень сигнала не может превышать напряжение питания микросхемы VCC.
- Сквозной ток через канал-перемычку не должен превышать 25 мА. Этого достаточно для управления обычными светодиодами.
- Собственное сопротивление канала около 55 ом.
Особенности работы мультиплексора
Вывод EN (Enable) управляет активностью микросхемы в целом. При высоком логическом уровне на входе EN все сигнальные выводы мультиплексора переходят в высокоомное состояние независимо от адреса на выводах S0…S3.
При низком логическом уровне на входе EN вывод Z соединяется с одним из выводов Y0…Y15, а остальные выводы Y находятся в отключенном (высокоомном) состоянии. Этот момент важно учитывать, если сигнал поступает на вывод Z, а приемники сигнала подключены к выводам Y. В этом случае входы всех приемников сигнала, кроме подключенного в данный момент к Z, будут “висеть в воздухе” и подвергаться случайным помехам. Обычно это недопустимо, и надо предусмотреть в схеме резисторы номиналом 5…10 кОм, которые будут подтягивать входы приемников к общему проводу.
Если адресные входы S0…S3 подключены к портам Arduino, то адрес выставляется не одномоментно, а по мере записи логических уровней в порты Arduino!!! Мультиплексор работает быстро, и в момент выставления адреса вывод Z на короткое время будет соединяться со случайными выводами Y. Иногда это может быть очень вредно – вы можете соединить Z с ненужным случайным выводом Y. А мы ведь знаем, что если сбой в схеме может случиться, то он обязательно произойдет с наихудшими последствиями в самое неудачное время.
Поэтому лучше занять еще один цифровой порт Arduino для управления выводом EN. Алгоритм работы такой:
- Подаем высокий уровень на вывод EN
- Выставляем номер вывода Y на входах S0…S3
- Подаем низкий уровень на вывод EN
Пример подключения к Arduino
Порты D0…D3 подключим к адресным входам S0…S3; порт D4 соединяем со входом EN. Вывод Z соединяем с аналоговым входом A0 (рис. 2).

Загружаем в плату Arduino простой скетч:
#define S0 0 #define S1 1 #define S2 2 #define S3 3 #define EN 4 void setup() { pinMode(EN, OUTPUT); digitalWrite(EN, HIGH); pinMode(S0, OUTPUT); digitalWrite(S0, LOW); pinMode(S1, OUTPUT); digitalWrite(S1, LOW); pinMode(S2, OUTPUT); digitalWrite(S2, LOW); pinMode(S3, OUTPUT); digitalWrite(S3, LOW); pinMode(A0, INPUT_PULLUP); pinMode(EN, OUTPUT); digitalWrite(EN, LOW); } void loop() { }
В этом скетче мы выставили на выводах S0…S3 адрес вывода Y0 и активировали мультиплексор. Теперь при помощи мультиметра измерьте сопротивление между выводом Z и выводами Y. Только между выводами Z и Y0 низкое будет сопротивление, остальные выводы Y отключены.
Измерьте напряжение на выводах Y. Почему на выводе Y0 напряжение питания? Правильно, потому что командой pinMode(A0, INPUT_PULLUP); мы включили внутренний подтягивающий резистор, который подтягивает вход A0 к линии питания. Соответственно, это же напряжение проникает через вывод Z на вывод Y0.
Обратите внимание, чтобы управлять светодиодами, подключенными к выводам Y, достаточно одного гасящего резистора в цепи вывода Z. Второй вывод резистора подключается к общему проводу или линии питания, в зависимости от полярности включения светодиодов. При подборе номинала резистора учитывайте собственное сопротивление канала около 55 ом.
а как подключить к демультиплексору аудио-декодер на MT8870?
Прежде всего, сформулируйте конечную задачу, хотя в виде блок-схемы или парой слов. Откуда и куда поступает сигнал, с какой целью? Вывод Z – это общий сигнальный вывод, который может соединяться с любым из выводов Y0-Y15 в зависимости от адреса на S0…S3. Например, если вы хотите подавать на вход MT8870 сигнал DTMF от разных источников, то соединяете вывод Z со входом MT8870, к выводам Y0…Y15 подсоединяете разные источники DTMF сигнала, и выбираете нужный источник выводами S0…S3.
Разумеется, если ваша задача другая, то и подключение будет другое. Помните, что у мультиплексора нет понятия “вход” и “выход”, он одинаково пропускает сигнал между Z и Y0…Y15 в любом направлении. Вы ведь знаете, как устроен галетный переключатель? Вот это и есть мультиплексор.
от звукоплаты компьютера звук диалтона идет на аудио-декодер DTMF на базе MT8870, там на выходах Q0-Q3 появляется код соответствующий диалтону, этот код передается на входы S0-S3 демультипексора, и в итоге на соответствующем диалтону выходе Y0-Y15 появляется лог 0. Ранее эта схема прекрасно работала в телефонах. Но сейчас я я хочу собрать эту же схему на модулях Arduino, и не могу понять, как соединить аудио-декодер DTMF Arduino с их же демультиплексором.. Однако если ранее для активации демультиплексора требовалось только подать лог 0 на свободный вход CS1 или CS2, то сейчас появились входы EN и Z, которые неизвестно как работают и что на них подавать.
вот и весь вопрос.
На вывод EN нужно подать логический 0. На вывод Z надо подать тот логический уровень, который вы хотите выдать на Y0-Y15. Поскольку вам нужен 0, значит подаете на Z тоже 0. Итого, просто сажаете на землю выводы EN и Z модуля мультиплексора.
не пойдет – выводы Y0-Y15 и так на нуле даже если схема выключена.
Должно быть так: при включении устройства в сеть на выходах Y0-Y15 устройства устанавливается +5 В, если же подается диалтон, то соответствующий выход Yi обнуляется.
Значит придется подключить подтягивающие резисторы от +5 к каждому выводу Yi. Неактивные выводы имеют высокий импеданс, и резисторы будут тянуть их в +5. Активный вывод будет через линию Z притягиваться к 0. Иначе никак. Перечитайте еще раз внимательно описание работы мультиплексора. Неактивные выводы не могут быть “и так на нуле”, как вы говорите. Они находятся в состоянии _высокого_импеданса_, а это далеко не то же самое, что логический ноль!
еще один вопрос, и начинаю паять: надо подтягивать +5 В сразу ко всем выходам Yi или можно по одному?
Нужно подключить отдельные подтягивающие резисторы между +5 и каждым выводом Yi, который вам нужен. Если вы используете все 16 выводов Yi, значит вам придется подключить 16 резисторов, потому что линии Yi абсолютно независимые друг от друга.
Большое спасибо!
Спасибо. Толково про выставление адресов, хоть и кажется очевидным на первый взгляд. А я думал откуда дребезг при считывании. А не могли-бы вы сказать как правильно реализовать обвязку при чтении портов, т.е. в случае когда микросхема работает как мультиплексор. Конденсаторы или триггер или ещё как-нибудь?
Если вы про эффект дребезга, который возникает при выставлении адреса мультиплексора, то здесь можно использовать программный триггер: отключать мультиплексор подачей EN=1, ставить адрес, включать мультиплексор подачей EN=0. Если речь про триггеры на входе портов, то можно использовать один триггер на общем выводе Z (если вы транслируете много входов в один). Но лучше использовать нормальную цифровую микросхему-экспандер. Ведь мультиплексор CD74HC4067 предназначен для коммутации аналоговых сигналов, и все остальные варианты – это нестандартное использование с вытекающими отсюда проблемами.
Спасибо, очень доходчиво. Да, именно эти два варианта интересовали. Ни какие другие варианты и не предпологаю. Но уже решил использовать рекомендованный вами в другой статье мультиплексор/демультиплексор по i2c – PCF8575. http://reedpaper.com/archives/835
Сейчас решаю как буриданов осёл, делать выводы с возможностью ШИМ, с общим питанием от блока питания 12-36 вольт, который запитывает отдельно через кренку и ПЛК, либо выводы с реле, как это принято в промышленных ПЛК.