К шине с экраном нужно добавить часы — и у каждого второго на этом шаге растут сомнения: не будут ли два модуля кричать одновременно, кому достанется провод, не сгорит ли что-нибудь. Сомнения красивые и напрасные: шина держит столько жильцов, сколько адресов вы найдёте, а выбор слушателя делает одно адресное слово в начале каждого кадра. Разбираю на паре, которая живёт почти в каждом моём проекте, — экран 0x27 и часы 0x68 — что физически происходит на двух проводах, как разведены их разговоры и что ломается, когда на шину попадают клоны с одинаковым адресом. Проводку и сборку такой пары показывал урок про экран и часы вместе — здесь я смотрю в саму шину, а не в скетч.
Пара выбрана не случайно: это самые частые соседи по макетке, и их адреса не пересекаются никогда — 0x27 у переходника экрана, 0x68 зашито в кристалле часов. На этой паре видно всё, что нужно знать о шине из двух устройств, включая то, чего на ней быть не должно. Токи у соседей мирные: экран с подсветкой тянет 25–30 мА, часы — меньше миллиампера, поэтому пару питает рейка макетки, а не пин 5V платы: на длинной шине из пяти жильцов разница уже заметна.
Одно адресное слово — один слушатель
Каждая передача начинается одинаково: мастер ставит старт-условие, отправляет семь бит адреса и бит направления, и на девятом такте ждёт подтверждения. Подтверждает тот единственный, чей номер совпал, — остальные чипы услышали чужой адрес и спят до стоп-условия. Часы на 0x68 просыпаются только на свои кадры, экран на 0x27 — на свои, и встретиться в эфире они не могут физически: говорит всегда мастер, слейвы лишь прижимают линию в ответ. Скелет этих вызовов разобрал урок про begin и endTransmission, чтение регистров часов — урок про requestFrom.
Разговор с часами в этом скетче двухходовка, и на ней видно ещё одно правило соседства. Сначала мастер пишет на 0x68 номер регистра — старт с адреса, один байт, стоп. Потом читает: старт, адрес с битом чтения, нужное число байтов, стоп. Между ходами мастер не отпускает очередь, а ставит повторный старт — шина всё это время числится занятой им, и экран 0x27 терпеливо ждёт своего окна. Указатель регистра в часах сам сдвигается после каждого прочитанного байта: секунды, минуты, часы идут подряд, поэтому один requestFrom на три байта забирает всё время целиком. Соседи об этом не знают и знать не должны — каждый разговаривает с мастером наедине.
Разводка при этом честно общая: четыре провода на модуль втыкаются в те же две сигнальные линии параллельно, отдельных пинов ни у кого нет. Лимит растёт не по числу устройств, а по ёмкости линий: стандарт NXP отводит 400 пФ, на практике это пара метров ленточного провода при 100 кГц. Подтяжки суммируются: два модуля с бортовыми резисторами по 10 кОм дают 5 кОм суммарной — норма; пять модулей уже около 2 кОм, шина греет резисторы, но живёт. Владельцем адреса прибор становится в момент совпадения — и ровно до стоп-условия.
#include <Wire.h>#include <LiquidCrystal_I2C.h>#include <RTClib.h> LiquidCrystal_I2C lcd(0x27, 16, 2);RTC_DS3231 rtc; unsigned long lastTick = 0; void setup() { Wire.begin(); Serial.begin(9600); lcd.init(); lcd.backlight(); if (!rtc.begin()) { Serial.println("Часы на 0x68 молчат - проверьте четыре провода"); while (1) delay(100); } lcd.setCursor(0, 0); lcd.print("LCD 0x27 | RTC 0x68");} void loop() { unsigned long ms = millis(); if (ms - lastTick >= 1000) { lastTick = ms; DateTime t = rtc.now(); // кадр на 0x68 lcd.setCursor(0, 1); // кадры на 0x27 lcd.print(t.hour()); lcd.print(":"); lcd.print(t.minute()); lcd.print(":"); lcd.print(t.second()); lcd.print(" "); }}Конфликт клонов: два чипа с одним адресом
Клоны попадают на шину незаметно: второй такой же переходник с невыпаянной перемычкой, вторая плата часов того же семейства, датчик из чужого набора. Для мастера всё выглядит прилично: на адресном слове линию прижимают оба чипа сразу, а линия с открытым стоком складывается по И — два прижатия неотличимы от одного здорового ACK. Поэтому сканер покажет не два устройства, а одно: конфликт не виден на этапе адресации в принципе. Записи при этом уходят обоим, и тут начинается специфика: два экрана покажут одно и то же — забавно, но безвредно; две энергонезависимые памяти перепишутся одинаково — уже тревожно.
Чтение ломается жёстче всего. Когда мастер читает байт, биты отдают оба чипа одновременно: нули любого из них прижимают линию, единицы тонут в чужих нулях, и мастер собирает побитное И из двух ответов. Часть байтов совпадёт случайно, часть превратится в кашу — картина, которую новички лечат переустановкой библиотеки. Теория столкновений и разбор пары-претендента на один номер были в уроке про конфликты адресов; увидеть кадры своими глазами помогает sniffer трафика.
| Сценарий | Что видит шина | Что делать |
|---|---|---|
| Экран 0x27 и часы 0x68 | каждый кадр подтверждает один адресат | ничего: это рабочая шина |
| Два клона на 0x27, только запись | двойной ACK как один, запись уходит обоим | развести адреса перемычкой или оставить, если дубль безвреден |
| Два клона на 0x27, нужно чтение | побитное И двух ответов: каша в байтах | обязательно развести адреса |
| Два DS3231: адрес зашит | один адрес 0x68, сканер видит одно устройство | мультиплексор TCA9548A или вторая шина SoftI2C |
Лечится конфликт по дешевизне: у переходников экрана — паяльником по площадкам A0–A2, у датчиков с адресными ножками — проводком к плюсу или земле, у целых семейств — выбором sibling-версии чипа вроде PCF8574A с базой 0x38. Дальше по цене — мультиплексор TCA9548A, который держит восемь изолированных веток и разобран в уроке про мультиплексор. Когда и перемычек нет, как у DS3231 с его зашитым 0x68, остаётся вторая шина на других пинах — программный I2C из урока про SoftI2C. Полную карту, кто на каком этаже живёт, ведёт таблица типовых адресов — перед покупкой второго модуля я смотрю туда, а не в описание продавца.
Правила роста шины у меня умещаются в три строки. Первая: карта адресов пишется до покупки второго модуля, не после — таблица типовых адресов и прогон сканера после каждого подключения. Вторая: модули подключаются по одному, и каждый новый жилец должен изменить распечатку сканера ровно на одну строку. Третья: часы крупным планом — их регистры, будильники и температуру разбирает урок про время на DS3231; экранная половина пары живёт в уроках про LCD. Когда жильцов становится больше пяти, я честно считаю не адреса, а ёмкость линий и подтяжки — именно они сдыхают первыми, а не номера.
Приятно, что отказоустойчивость у такой пары врождённая. Если экран отвалится — провод выдернут, чип сгорел, — часы продолжат тикать: мастер получит двойку на адресе 0x27, пропустит перерисовку и уйдёт читать время. Если сдохнут часы, экран останется жить, только строка времени закостенеет. Плохо для обоих только одно: зависший слейв, придавивший линию, — он глушит всех разом, и выручает оттуда вся шина вместе, как учил урок про зависание и таймаут. Поэтому в ответственных проектах я опрашиваю соседей по очереди и веду каждому свой счётчик отказов: один промах — случайность, три подряд — жилец выпал, продолжаем без него.
Что видит шина в спокойной паре, стоит один раз посмотреть сниффером и запомнить на всю жизнь: старт, 0x27, байты, стоп; старт, 0x68, байт регистра, рестарт, чтение, стоп. Два разговора, одна линия, ноль накладок. Вся магия сосуществования умещается в девятый такт адресной рамки — и это, по-моему, самая элегантная инженерная сделка в электронной музыке периферии.
- 1. На шине экран 0x27 и часы 0x68. Мастер шлёт адрес 0x27. Кто отвечает?
- 2. На шине два клона с адресом 0x27. Что покажет сканер?
- 3. Мастер читает байт с двух клонов на 0x27. Что придёт?
- 4. Как развести два модуля DS3231 на одной шине?
- 5. У экрана и часов на борту подтяжки по 10 кОм. Суммарная подтяжка шины?
- Адресное слово в начале кадра — селектор слушателя: подтверждает один совпавший, остальные спят до стоп-условия
- Экран 0x27 и часы 0x68 разводятся автоматически: провода общие, разговоры разные, лимит ставит ёмкость линий около 400 пФ
- Бортовые подтяжки модулей складываются параллельно: два по 10 кОм — 5 кОм, пять модулей — около 2 кОм
- Клоны с одним адресом дают двойной ACK, неотличимый от здорового: сканер видит один адрес, запись уходит обоим, чтение собирается по И
- DS3231 без перемычек: пары одинаковых часов разводят мультиплексором TCA9548A или SoftI2C на свободных пинах
Частые вопросы по теме урока
- На шине экран 0x27 и часы 0x68. Мастер шлёт адрес 0x27. Кто отвечает?
- Адресное слово выбирает единственного слушателя. Часы просыпаются только на свой 0x68 и спят до стоп-условия — встретиться в эфире соседи не могут. Только экран: часы молчат до стоп-условия
- На шине два клона с адресом 0x27. Что покажет сканер?
- Линия с открытым стоком складывается по И: два чипа прижимают её вместе, и для мастера это один живой ACK. Сканер конфликт на адресации не видит. Один адрес: двойной ACK выглядит как здоровый ответ
- Мастер читает байт с двух клонов на 0x27. Что придёт?
- Оба чипа тянут линию на своих нулях, единицы тонут в чужих нулях. Мастер собирает побитное И: часть байтов совпадает случайно, часть ломается. Каша: каждый бит сложится по И из двух ответов
- Как развести два модуля DS3231 на одной шине?
- У DS3231 перемычек нет: 0x68 зашит заводом. Два таких модуля разводит только мультиплексор с изолированными ветками или программная шина на других пинах. Мультиплексором TCA9548A или второй шиной SoftI2C
- У экрана и часов на борту подтяжки по 10 кОм. Суммарная подтяжка шины?
- Параллельные резисторы уменьшаются: десять килоом пополам — пять. Это норма; хуже, когда модулей пять и сумма падает к двум килоом и ниже. Около 5 кОм: резисторы сложились параллельно