Пять модулей для метеостанции приехали одной посылкой: LCD1602 с переходником, экранчик OLED на 0,91 дюйма, часы DS3231, датчик давления BME280 и гироскоп MPU6050. Я развесил всех на одной шине и запустил сканер из урока про поиск адресов — тот самый, что живёт у меня в закладках с 2019 года. Сканер напечатал четыре адреса: 0x27, 0x3C, 0x68, 0x76. Пять модулей, четыре адреса — и ни одна программа в мире не подпишет, где чей дом: сканер видит только номера.
Хуже было с 0x68: кандидатов на этот адрес у меня оказалось двое — часы и гироскоп, у обоих он прошит производителем. В этом уроке я собрал свою адресную книгу: кто обычно живёт на каждом номере, какие модули сталкиваются лбами на одной шине и как их разводить по разным квартирам. Сканер даёт список адресов за секунду, а вот понять, что за модуль прячется за 0x68, — уже работа для этой таблицы.
Семибитный адрес: почему в даташите другое число
Сначала деталь, на которой я споткнулся первым. Адрес I2C-устройства занимает семь бит — от 0x03 до 0x77, и библиотека Wire ждёт именно семибитный вид: beginTransmission(0x68). Но в старых даташитах и в памятках к китайским модулям часто написано восьмибитное число: те же часы фигурируют там как 0xD0 для записи и 0xD1 для чтения. Это не другой адрес, а тот же, сдвинутый на бит влево: старшие семь бит — адрес, самый младший бит — направление обмена, и Wire выставляет его сама.
Отсюда моё правило на всю жизнь: если в источнике два соседних числа, отличающихся только последним битом, дели большее пополам. Модуль, который в статье числится как 0x4E/0x4F, после деления превращается в знакомый 0x27 — да это же LCD-переходник. Память, записанная как 0xA0/0xA1, на самом деле живёт на 0x50. Проверить себя легко сканером: настоящий адрес всегда попадает в диапазон до 0x77, а «раздутый» восьмибитный сразу выдаёт себя значениями выше — на живой шине выше 0x77 никто не прописан.
Если вся эта история с пинами A4/A5, подтяжками и диапазоном адресов для вас с нуля — начните с первого урока раздела про шину I2C, а потом возвращайтесь: таблица ниже станет логичным продолжением.
Кстати, о скорости опроса. Одна проба адреса — это START, байт адреса, подтверждение и STOP; при 100 кГц на неё уходит около трети миллисекунды. Полный прогон по 117 адресам занимает десятки миллисекунд чистой шины, так что даже с паузами между находками сканер укладывается в секунду. Мой вывод простой: просканировать шину можно хоть в каждом проходе loop() отладочной сборки — это не та операция, которую нужно беречь.
| Адрес | Кто там обычно живёт | Чем этот адрес коварен |
|---|---|---|
| 0x20–0x27 | Переходник PCF8574 для LCD1602 | Внутри диапазона сидит датчик света BH1750 (0x23) — при переставленных джамперах возможна встреча |
| 0x38–0x3F | Переходник PCF8574A — вторая партия LCD | 0x3C может занять OLED: два дисплея дерутся за один номер |
| 0x3C | OLED-экран SSD1306 (реже 0x3D) | Тот же конфликт зеркалом: LCD-переходник с джамперами на 0x3C |
| 0x50–0x57 | Энергонезависимая память 24Cxx | Номер внутри диапазона выбирают ножки A0–A2 микросхемы |
| 0x68 | Часы DS1307/DS3231 и гироскоп MPU6050 | Самый частый конфликт на любительской шине: два разных модуля с одним адресом |
| 0x76–0x77 | Датчики погоды BME280/BMP280 | Ножка SDO переключает датчик между этими двумя адресами |
Таблица читается так: слева — точный адрес или диапазон, внутри которого модуль может оказаться в зависимости от джамперов. У переходника PCF8574 три ножки A0–A2 дают восемь позиций подряд: замкнул одну — и вместо 0x27 получите 0x26. У памяти 24Cxx та же система с тремя ножками. А вот OLED и часы обычно идут с заводским адресом без вариантов — поэтому в книге они указаны одним числом, а не диапазоном.
Сверяясь с таблицей, держите в голове, что у одного типа модулей бывают разные партии. Тот же датчик света BH1750 у одних продавцов отвечает на 0x23, у других — на 0x5C: решает ножка ADDR на плате. Так что адресная книга — это прицел, а сканер — выстрел: книга сужает список кандидатов, сканер называет победителя. Мой порядок не меняется годами: подключил, просканировал, сверился с таблицей, записал найденный адрес комментарием в шапку скетча — через полгода благодарил себя за эту строчку.
Кто с кем сталкивается и как разводить
Теперь про столкновения. Адрес 0x68 — самый конфликтный: на нём прописаны и часы DS1307/DS3231, и гироскоп-акселерометр MPU6050. Я однажды повесил обоих рядом — и получил кашу: сканер видел один адрес, байты часов перемешивались с байтами гироскопа, а время в проекте с DS3231 жило своей жизнью. Диагноз ставится быстро: если на шине обнаружился 0x68, а вы помните про двух кандидатов — это они делят одну квартиру.
Разводить соседей нужно через ножку выбора адреса, и двигают обычно того, у кого она есть. У DS3231 на готовом модуле никаких джамперов нет — адрес намертво 0x68. Зато у MPU6050 есть ножка ADO: притяните её к питанию — и гироскоп переедет на 0x69, унося конфликт с собой. То же у датчиков давления: ножка SDO выбирает между 0x76 и 0x77. Моё правило простое: модуль без ножек выбора — неприкосновенен, переезжает тот, кто умеет. Проверка после переезда — всё тот же сканер: на шине должны появиться оба адреса, 0x68 и 0x69, и на каждом — один жилец.
Пара слов про экраны, потому что там конфликт неочевиден. OLED на SSD1306 занимает 0x3C (когда и 0x3D — об этом в уроке про первый OLED), а LCD-переходники второй партии, на PCF8574A, раскидались по диапазону 0x38–0x3F. Если у такого переходника джамперы выставлены на 0x3C — два дисплея дерутся за один адрес; я честно ловил эту пару на своём столе: экраны по очереди показывали куски чужого текста. С LCD на 0x27 такая беда не случится — это чужой диапазон.
Когда развести нечем — у всех участников адрес прошит без ножек выбора — зовут тяжёлую артиллерию: мультиплексор TCA9548A. Он сам сидит на 0x70–0x77 и подключает к мастеру до восьми одинаковых датчиков по очереди, по одной внутренней шине за раз. Для пары модулей это оверкилл, для восьми одинаковых BH1750 — единственный способ. И ещё деталь напоследок: диапазон PCF8574 начинается с 0x20, а фотодатчик BH1750 со своим дефолтным 0x23 сидит прямо внутри него. По умолчанию переходник на 0x27 — мир, но переставьте его джамперы на 0x23 — и производители, не думавшие друг о друге, столкнутся на вашей макетке.
#include <Wire.h> byte found[8]; // найденные адресаint count = 0; void scan() { count = 0; for (byte addr = 8; addr <= 119; addr++) { // 0x08-0x77 Wire.beginTransmission(addr); if (Wire.endTransmission() == 0) { found[count] = addr; count++; } }} void whoIs(byte addr) { switch (addr) { case 0x27: Serial.println(" LCD1602 на PCF8574"); break; case 0x3C: Serial.println(" OLED SSD1306 (или LCD на 0x3C!)"); break; case 0x50: Serial.println(" Память 24Cxx"); break; case 0x68: Serial.println(" Часы DS3231 или MPU6050 - проверь ADO"); break; case 0x76: Serial.println(" Датчик давления BME280/BMP280"); break; default: Serial.println(" Незнакомец - нужен даташит"); }} void setup() { Wire.begin(); Serial.begin(9600);} void loop() { Serial.println("Сканирую шину..."); scan(); Serial.print("Найдено адресов: "); Serial.println(count); for (int i = 0; i < count; i++) { Serial.print("0x"); if (found[i] < 16) Serial.print("0"); Serial.print(found[i], HEX); Serial.print(" -"); whoIs(found[i]); } delay(5000);}По строкам. scan() гонит пару beginTransmission/endTransmission по каждому адресу от 0x08 до 0x77 — младшие номера пропускаю сознательно: они зарезервированы стандартом под служебные цели, и устройства там встречаются только в экзотике. Каждый отклик запоминается в массив found[], а счётчик живёт в отдельной переменной — так потом несложно напечатать и список, и итог.
whoIs() — адресная книга в форме switch: она печатает предположение, а не истину. Случай 0x68 подписан двояко — до нажатия ADO не угадаешь, часы это или гироскоп. Ведущий ноль в печати if (found[i] < 16) добавляет малозаметную, но важную вещь: без него адрес 0x07 печатался бы как 0x7, и глаза при сверке с заметками цепляются хуже.
Такая связка — сканер плюс адресная книга — закрывает девять случаев из десяти. Нашёл 0x27 — подставляй адрес в LCD-скетч; нашёл 0x50 — перед тобой память вроде той, что мы трогали в уроке про EEPROM; нашёл 0x68 — уточняй, часы это или гироскоп. Десятый случай, когда адресов на всех не хватило, лечится джамперами или мультиплексором — о нём будет отдельный урок в этом разделе. Мою бумажную версию таблицы, полсотни адресов на листе А5, я распечатал один раз и подклеил внутрь коробки с макетками — дешевле, чем гуглить каждый раз.
А следующий урок я посвятил анатомии самой библиотеки Wire: что делает begin(), куда падают байты от write() и почему на линиях ничего не происходит до endTransmission().
- Wire принимает семибитные адреса 0x03–0x77; 0xD0 из даташита — это 0x68, сдвинутый на бит влево
- 0x27/0x3F — LCD-переходники PCF8574(A); 0x3C — OLED; 0x50–0x57 — память 24Cxx; 0x76–0x77 — BME280/BMP280
- 0x68 делят часы DS3231 и гироскоп MPU6050 — самый частый конфликт на любительской шине; опознать виновника помогает регистр WHO_AM_I
- Часы адрес не сменят, поэтому переезжает тот, у кого есть ножка выбора: ADO у MPU6050, SDO у BMP280, ADDR у BH1750
- Сканер даёт номера, адресная книга называет жильцов; тупиковый случай — мультиплексор TCA9548A на 0x70–0x77
- 1. Сколько бит занимает адрес, который нужно передать в Wire.beginTransmission()?
- 2. Кто обычно живёт на адресе 0x3C?
- 3. На шине часы DS3231 и MPU6050 — оба на 0x68. Что делать?
- 4. В старой статье датчик числится как 0x90/0x91. Что писать в Wire?
- 5. Сканер нашёл 0x50. Наиболее вероятный жилец:
Частые вопросы по теме урока
- Сколько бит занимает адрес, который нужно передать в Wire.beginTransmission()?
- Wire ждёт семибитный адрес; восьмибитные числа из даташитов вроде 0xD0 — это сдвиг влево, а младший бит — направление обмена. 7 бит
- Кто обычно живёт на адресе 0x3C?
- 0x3C — типовой адрес SSD1306. LCD-переходники занимают 0x20–0x27 или 0x38–0x3F, часы — 0x68, память — 0x50–0x57. OLED-экран SSD1306
- На шине часы DS3231 и MPU6050 — оба на 0x68. Что делать?
- Часы свой адрес не меняют, а у MPU6050 есть ножка ADO: высокое напряжение на ней переносит модуль на 0x69. Подтянуть ADO гироскопа к питанию — он переедет на 0x69
- В старой статье датчик числится как 0x90/0x91. Что писать в Wire?
- Два соседних числа — восьмибитная форма с битом направления: 0x90 делим пополам и получаем семибитный адрес 0x48. 0x48
- Сканер нашёл 0x50. Наиболее вероятный жилец:
- 0x50–0x57 — микросхемы EEPROM 24Cxx. Номер ячейки внутри памяти и адрес на шине — разные вещи. LCD1602 с переходником