Табло для мастерской я задумал из восьми одинаковых экранов 0,96 дюйма: по экрану над каждым станком, и на всех — счётчик деталей. Экраны брал одной партией, и все восемь вышли с адресом 0x3C, как и положено SSD1306 без перемычек. Адресную ножку производитель не вынес наружу: на платке ровно четыре отверстия — питание, земля, SDA, SCL. Развести их нечем, второй мастер-платы в проекте тоже не было. Я уже прикидывал, как тяну на каждый экран отдельные два пина и где возьму ещё четырнадцать линий, когда вспомнил, что в уроке про конфликт адресов мелькал запасной выход — мультиплексор TCA9548A. Достал с полки платку 15 на 13 миллиметров за полторы сотни рублей, посадил её между Uno и шлейфами — и через полчаса все восемь экранов жили на тех же двух проводах A4 и A5.
TCA9548A — не второй мастер и не переключатель проводов на реле, а честный перекрёсток: с одной стороны мастер-шина от Uno, с другой — восемь независимых подшин SD0-SCL0 и дальше до SD7-SCL7. В этом уроке разберём, как канал выбирается одним байтом, откуда берутся адреса 0x70-0x77, что происходит с подтяжками на подшинах и почему длинный шлейф одного канала перестаёт душить соседей. Договоримся и о честности: самого чипа в виртуальной схеме нет, заглушка шины принимает всё — зато панель I2C покажет ровно тот трафик, который ушёл бы на живую плату.
Перекрёсток с восемью выходами
Внутри чипа — восемь пар ключей: мастер-шина попеременно замыкается на выбранную пару SDn-SCLn. Отсюда первое полезное следствие: у каждой подшины свои два провода и своя ёмкость, и предел в 400 пФ считается для каждой отдельно. Длинный шлейф на SD5 не отнимает ни пика запаса у коротких соседей — раньше вся шина мучилась от худшего куска провода, теперь каждый канал живёт своей длиной. Это же оружие против медленных датчиков: капризный модуль на своём канале больше не тормозит остальных. Бонус от архитектуры — изоляция при сбое: залипший слейв, прижавший SDA к земле, отрезается от мастера закрытием его канала байтом 0x00, и остальные семь устройств продолжают работать, будто ничего не случилось. Без мультиплексора тот же залипший слейв укладывал бы всю шину целиком.
Второе следствие — уровни. Чип питается от 1,65 до 5,5 В и умеет сводить шины с разным напряжением: 3,3-вольтовые датчики на подшине спокойно живут рядом с 5-вольтовой Uno, если подтяжки именно той подшины подняты к 3,3 В. Получается уровневый мостик на одном чипе, хотя обычно между 3,3 и 5 В приходится городить согласование — я это разбирал с резисторными делителями в уроке про совместимость 3,3 и 5 вольт. Мультиплексор решает вопрос раньше, чем он успевает стать проблемой. Одно условие: подтяжки ставятся по обе стороны — мастера к 5 В, подшины к 3,3 В; одна общая подтяжка не поднимет линию до нужного уровня никому, и «полуподнятые» фронты проявятся как редкие NACK в самых жирных кадрах.
Свой адрес у мультиплексора выбирается ножками A0-A2: все на земле — 0x70, каждая поднятая ножка добавляет по единичке, потолок 0x77. Механика та же, что у расширителя PCF8574, и адресная книга из урока про таблицу адресов сюда ложится целиком. На готовых модулях ножки адреса подтянуты дорожками платы; если паяете голый чип, не оставляйте A0-A2 висящими в воздухе — адрес поплывёт, и сканер покажет ерунду. На одной мастер-шине уживается до восьми мультиплексоров — это уже 64 подшины, больше не потребуется ни одному моему проекту. Канал выбирается одним байтом: бит n включает подшину n. Записали 1 — открыт нулевой канал, 4 — второй, 0x00 — закрыты все. Хитрость: можно включить несколько бит сразу, например маску 0b00000011, — тогда посылка уйдёт на две подшины разом. Для записи одной конфигурации восьми одинаковым датчикам это подарок; на чтение так ходить нельзя — отвечать будут все открытые каналы одновременно и устроят на SDA толкучку.
| Способ | До скольких устройств | Что потребуется | Грабли |
|---|---|---|---|
| адресная ножка ADO/SDO/ADDR | в два раза больше | перекинуть ножку к земле или питанию | есть не у всех чипов: MPU6050 так переезжает на 0x69, а SSD1306 — нет |
| джамперы A0-A2 на чипе | 8 адресов | перемычки на платке | в даташитах адреса восьмибитные: 0xD0 вместо 0x68 |
| мультиплексор TCA9548A | 8 подшин × 8 устройств = 64 | один чип, два провода к мастеру | канал надо переключать перед каждым разговором |
| вторая плата-мастер | не ограничено | вторая Arduino и обмен между мастерами | два набора кода и протокол их разговора |
Схема до смешного короткая: VCC, GND, SDA и SCL уходят к Uno на A4 и A5, восемь пар SDn-SCLn ждут устройства. В скетче появляется одна функция tcaselect(kanal): beginTransmission на 0x70, байт 1 << kanal, endTransmission. Дальше — обычный разговор с устройством, как будто других подшин и нет. В моём табло скетч обходит каналы по кругу и просит каждый экран зажечь всю матрицу: командой 0xA5 из даташита SSD1306, о которой мы говорили в уроке про первый вывод на OLED. Экран, залитый светом целиком, видно издалека — мгновенная проверка, что переключение дошло до нужной подшины. Код возврата endTransmission здесь работает как контроль: ноль значит, что на этой подшине кто-то дома. На моём табло шлейфы шли по 30-40 сантиметров, и каналы жили на подтяжках мастера; на стеллаже с полуметровыми связками пришлось ставить по резистору на канал — границу разберём ниже. Как расшифровывать остальные коды — отдельная история, ей посвящён следующий урок этого трио.
#include <Wire.h> const byte MUX = 0x70; // TCA9548A: ножки A0-A2 на землеconst byte EKRAN = 0x3C; // одинаковый адрес на всех подшинах void tcaselect(int kanal) { Wire.beginTransmission(MUX); Wire.write(1 << kanal); // бит n открывает подшину n Wire.endTransmission();} void setup() { Wire.begin(); Serial.begin(9600); Serial.println("Восемь подшин: экраны 0x3C по кругу");} byte k = 0; void loop() { tcaselect(k); Wire.beginTransmission(EKRAN); // дальше — обычный разговор с экраном Wire.write(0x00); // байт команд SSD1306 Wire.write(0xA5); // «вся матрица горит» — видно издалека int kod = Wire.endTransmission(); // 0 = экран на этой подшине ответил Serial.print("ch="); Serial.print(k); Serial.print(" kod="); Serial.println(kod); k++; if (k > 7) k = 0; delay(400);}Подтяжки, каналы и что видно в симуляторе
Подтяжки распределяются так: на мастер-шине они обязательны, обычно хватает бортовых 4,7 кОм модулей или своих резисторов — номиналы считались в уроке про номиналы подтяжек. Ключи мультиплексора пассивные, поэтому подтяжка мастера «дотягивается» через открытый канал: на коротких связках до полуметра ничего дополнительного не ставлю. Как только канал уходит длинным шлейфом — вешаю свои 4,7 кОм прямо на ту подшину, а про длину и её цену вспоминаю урок про длину проводов. Граница у меня простая: до полуметра живём на подтяжках мастера, дальше — по резистору на канал.
Ещё одно тихое свойство: обесточенный мультиплексор размыкает все ключи. Мастер увидит на подшинах тишину, а сам чип перестанет отвечать на 0x70 — и по коду пинга это опознаётся за секунду, о чём подробности во втором уроке трио. В симуляторе ни мультиплексора, ни обрывов нет: заглушка шины ACK-ает всё и всегда возвращает ноль. Зато трафик подлинный: панель I2C на каждый шаг покажет маску на 0x70 и вслед за ней стук в 0x3C. Пустой пакет без байтов данных в логе выглядит как START и сразу STOP — это и есть «стук в дверь», только адрес и подтверждение.
Эксперименты для закрепления
Первое: откройте два канала разом — напишите tcaselect с маской (1 << k1) | (1 << k2) — и разошлите команду 0xA5 двум экранам одной посылкой; на чтение так не ходите, толкучка на SDA обеспечена. Второе: закройте все каналы байтом 0x00 и прогоните пинг по 0x3C — на живой плате вернётся 2, «по адресу никого», и вердикт по этому коду разбирается в соседнем уроке трио. Третье: посадите на SD0 экран, а на SD1 — часы DS3231 из урока про время на этом чипе: разнобой устройств на разных подшинах — штатный режим мультиплексора, и оба домена не будут мешать друг другу даже при разных напряжениях подтяжек.
Четвёртое: пересадите мультиплексор на 0x71, подняв ножку A0 к питанию, и обновите константу MUX — убедиться, что чип переехал, можно обычным сканером шины: он показывает живых жильцов за минуту. И последнее, на живой плате: включите питание мультиплексора через кнопку и снимите её на полсекунды во время работы — мастер мгновенно потеряет все восемь подшин и найдёт их обратно, когда питание вернётся. Для табло, которое работает сутками, я в loop добавляю проверку пинга раз в десять секунд: чип вернулся из обесточенного состояния — канал открывается заново, и никто в мастерской этого даже не заметит.
- TCA9548A — восемь независимых подшин за два провода мастера: свой адрес 0x70-0x77, ножки A0-A2
- Канал открывается одним байтом: 1 << n; маска 0x00 закрывает всё; несколько бит сразу — для записи, не для чтения
- У каждой подшины своя ёмкость: длинный шлейф одного канала не душит соседей, лимит 400 пФ считается отдельно
- Чип питается от 1,65 до 5,5 В и сводит шины с разными подтяжками: 3,3-вольтовые датчики рядом с 5-вольтовой Uno
- tcaselect стоит вплотную к beginTransmission: мультиплексор хранит последнюю маску, пока не получит новую
- 1. Сколько отдельных шин даёт один TCA9548A?
- 2. Какой байт включает подшину номер 5?
- 3. Адрес TCA9548A при всех ножках A0-A2 на земле:
- 4. На живой плате пинг пустой подшины вернёт из endTransmission:
- 5. Сколько мультиплексоров уживается на одной мастер-шине?
Частые вопросы по теме урока
- Сколько отдельных шин даёт один TCA9548A?
- Восемь пар SDn-SCLn: у каждой подшины свои провода, своя ёмкость и лимит 400 пФ. восемь
- Какой байт включает подшину номер 5?
- Бит n включает канал n: 1 << 5 = 0x20. Байт 0x05 открыл бы каналы 0 и 2 сразу. 0x20
- Адрес TCA9548A при всех ножках A0-A2 на земле:
- База мультиплексора — 0x70; каждая поднятая ножка адреса добавляет единичку, потолок 0x77. 0x70
- На живой плате пинг пустой подшины вернёт из endTransmission:
- По адресу никого — NACK на адрес, код 2. В симуляторе заглушка всегда отвечает нулём. код 2
- Сколько мультиплексоров уживается на одной мастер-шине?
- Восемь адресов 0x70-0x77 — восемь чипов, и на каждом по восемь подшин: 64 независимые пары проводов. восемь — это до 64 подшин