Руководство · Начальный · 30 мин
Как работает шина I2C: адреса и подтягивающие резисторы
Два провода и общая шина: зачем нужны подтягивающие резисторы, почему несколько отладочных плат мешают друг другу и как устранить конфликт адресов.
Введение
На страницах этого сайта про датчики пишут подключить SDA и SCL, но нигде не объясняют, что делают эти два провода. Чаще всего знать это не нужно: вы подключаете их, библиотека работает, и датчик считывает данные.
Потом вы добавляете вторую плату, и первая перестаёт отвечать. Или библиотека возвращает нули без ошибки. Или выясняется, что два устройства хотят один адрес, а в документации ничего не сказано, что с этим делать.
Все эти симптомы вызваны одним и тем же небольшим набором фактов об I²C, и их меньше, чем следует из числа симптомов.
Два провода, много устройств
I²C подключает все устройства к одной общей паре проводов:
- SDA — линия данных.
- SCL — линия тактовой частоты; ею управляет контроллер, хотя устройство может удерживать её на низком уровне для растяжения тактовой частоты.
На Arduino Uno это A4 и A5 (и дублирующие выводы рядом с AREF — те же два вывода, а не дополнительные). Каждое устройство подключается к тем же двум проводам параллельно. Отдельного провода выбора микросхемы нет, и кольца нет: чтобы добавить устройство, припаяйте его к той же паре.
Именно поэтому шина так хорошо масштабируется для роботов. MPU-6050, VL53L0X и PCA9685 используют одни и те же два провода, а различаются по адресу, а не по разводке.
Никто не переводит линию в высокий уровень
Вот факт, из которого следует всё остальное.
Устройство I²C может только опустить линию на низкий уровень. Оно не может перевести её в высокий уровень: выход с открытым стоком — это переключатель на землю и ничего больше. Без внешнего воздействия линия плавала бы при произвольном напряжении.
Подтягивающие резисторы подтягивают линию к высокому уровню. Это не средство повышения надёжности и не необязательное дополнение; это половина электрической цепи. Без них у шины нет состояния покоя, и ничего не работает.
Выход с открытым стоком имеет реальное преимущество, поэтому его и используют: если два устройства говорят одновременно, одно опускает линию, а другое отпускает её, результатом будет низкий уровень. Ничего не конфликтует, ничего не замыкается, а проиграшее устройство может это обнаружить. На шине, где говорить может любое устройство, это важно.
Окно, в котором должен жить подтягивающий резистор
Ограничения есть с обеих сторон, и их можно вычислить.
Слишком малое значение — и ни одно устройство не сможет опустить линию. Спецификация требует, чтобы устройство обеспечивало ток стока не менее 3 mA, удерживая линию ниже 0.4 V, поэтому:
R_min = (Vcc − V_OL) / I_sink = (5 − 0.4) / 0.003 = 1533 Ω
Слишком большое значение — и нарастающий фронт будет слишком медленным. Линия поднимается по RC-кривой относительно ёмкости шины, а тактовая частота не будет ждать:
t_rise ≈ 0.85 × R × C ≤ 1000 ns at 100 kHz, ≤ 300 ns at 400 kHz
Теперь часть, которая сбивает с толку. Почти на каждой любительской отладочной плате уже установлены свои подтягивающие резисторы, обычно 4.7 kΩ. Если подключить несколько плат к одной шине, эти резисторы окажутся параллельно:
| Плат на шине | Эффективное сопротивление подтягивающих резисторов | Вердикт |
|---|---|---|
| 1 | 4700 Ω | Нормально |
| 2 | 2350 Ω | Нормально |
| 3 | 1567 Ω | На границе — 34 Ω выше нижнего предела |
| 4 | 1175 Ω | Ниже нижнего предела |
Поэтому отказ имеет определённую форму: один датчик работает, два работают, три работают в удачный день, а четвёртая плата останавливает всю шину. Ничего не сломано. Устройства просто больше не могут опустить линию достаточно низко, чтобы это считалось низким уровнем.
Исправление — удалить подтягивающие резисторы со всех плат, кроме одной. Обычно это два маленьких резистора для поверхностного монтажа с маркировкой 472, и документация платы указывает, где они находятся. Выпаивание в первый раз кажется неправильным, но это верное решение.
Просканируйте шину до любой другой отладки
Прежде чем трогать библиотеку, спросите у шины, что на ней находится. Этот скетч пробует каждый адрес и сообщает, какие отвечают:
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
while (!Serial) {}
Serial.println(F("Scanning I2C..."));
uint8_t found = 0;
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.print(F(" device at 0x"));
Serial.println(addr, HEX);
found++;
}
}
Serial.println(found ? F("done") : F("nothing answered — check wiring and pull-ups"));
}
void loop() {}
Результат показывает, какая у вас проблема:
- Никто не отвечает → проблема в проводах, питании или отсутствии подтягивающих резисторов. Не в библиотеке.
- Устройство отвечает по неожиданному адресу → вывод для установки адреса настроен иначе, чем вы предполагали.
- Устройство отвечает, но библиотека возвращает нули → шина исправна, а проблема находится выше неё.
Последняя строка стоит больше всего остального в этом скетче. Она чётко отделяет «неправильно подключён провод» от «неправильно написан код», а без этого на отладку уходит большая часть времени.
Адреса и путаница с 0xD0
Адрес I²C занимает 7 бит. Шестнадцать значений зарезервированы, остаётся 112 пригодных.
Вот ловушка. На проводе адрес передаётся как семь битов, за которыми следует бит чтения/записи, поэтому он выглядит как 8-битное значение. В технических описаниях часто приводят именно эту 8-битную форму. Библиотека Arduino Wire ожидает 7-битный адрес.
В техническом описании MPU-6050 указано, что его адрес равен 0xD0 для записи и 0xD1 для чтения. Библиотека Wire ожидает 0x68:
0xD0 = 1101 0000
0x68 = 0110 1000 the same bits, shifted right by one
Если устройство не отвечает по адресу, напечатанному в его техническом описании, сначала попробуйте сдвинуть это значение вправо на один разряд, и только потом делайте вывод, что плата неисправна. Это самая распространённая ошибка в I²C.
Когда два устройства хотят один адрес
Адреса задаются производителем, поэтому конфликты совершенно обычны. Есть три исправления — в порядке предпочтительности:
1. Вывод для установки адреса. Самое дешёвое исправление, если у компонента есть такой вывод. MPU-6050 находится по адресу 0x68 или по 0x69, если его вывод AD0 подтянут к высокому уровню, поэтому два таких устройства сосуществуют с одним проводом. У PCA9685 есть шесть паяемых перемычек, дающих 64 адреса, поэтому на одной шине можно подключить до 62 плат.
2. Удерживать остальные в сбросе, пока меняете адрес одного. У некоторых компонентов адрес фиксирован, но его можно перепрограммировать во время работы. VL53L0X всегда выходит с завода с адресом 0x29, и это стандартный способ запуска нескольких устройств: удерживайте вывод XSHUT каждого датчика на низком уровне, поднимите один, скажите ему перейти на новый адрес и повторите. Новый адрес хранится в RAM, поэтому последовательность повторяется при каждой загрузке.
3. Мультиплексор. TCA9548A — это одно устройство по адресу 0x70 с восемью переключаемыми шинами за ним. Выберите канал, поговорите с устройством на нём, выберите следующий. Это решение для восьми одинаковых датчиков без вывода для установки адреса и без перепрограммирования — ценой дополнительного компонента и того, что шина обслуживается по одному устройству за раз.
Скорость, длина и реальные причины отказов
I²C проектировалась для работы между микросхемами на одной плате. Робот растягивает её через всё шасси, и именно там ограничения начинают давать о себе знать.
- Главное ограничение — ёмкость, а не длина. Спецификация допускает суммарно 400 pF. Ленточный кабель добавляет примерно 50–100 pF на метр, а каждое устройство — около 10 pF. Длинные трассы отказывают из-за слишком медленного нарастающего фронта — на рисунке выше это видно как падение предела.
- Сначала замедлитесь, потом сдавайтесь.
Wire.setClock(50000)вдвое снижает стандартную частоту и даёт реальный запас на граничной шине. Роботу, опрашивающему датчик с частотой 100 Hz, не нужны 400 kHz. - Держите SDA и SCL раздельно. Если провести их рядом в ленточном кабеле, фронты тактовой частоты наводятся на данные. Провод земли между ними помогает.
- Растяжение тактовой частоты. Устройству, которому нужно время, может удерживать SCL на низком уровне, и контроллер должен ждать. Реальные аппаратные реализации I²C поддерживают растяжение тактовой частоты; некоторые реализации с программным формированием сигналов — нет, и симптомом становится устройство, которое работает в одиночку, но портит данные при загруженной шине.
- Зависшая шина. Если устройство было сброшено посреди передачи, оно может навсегда удерживать SDA на низком уровне, и каждый скан возвращает пустоту. Девять импульсов по SCL позволяют ему закончить байт, который он считал отправляемым, и отпустить линию — именно это делает процедура восстановления в хорошей библиотеке.
Смешивание 3.3 V и 5 V
ESP32 и Raspberry Pi работают с I²C при 3.3 V, а Uno — при 5 V. Поскольку шина имеет выход с открытым стоком, напряжение подтягивания задаёт высокий уровень для всех находящихся на ней. Если подтянуть её к 5 V при подключённом компоненте, рассчитанном только на 3.3 V, вы подадите 5 V на вывод с допустимым напряжением 3.6 V.
Два приёма спасают почти всегда, и стоит знать, на какой из них вы полагаетесь:
- Многие отладочные платы, «совместимые с 5 V», содержат микросхему на 3.3 V, регулятор и уже установленное преобразование уровней. Проверяйте до предположений — наличие только регулятора напряжения не означает, что сигнальные выводы защищены.
- Там, где его нет, стандартный ответ — двунаправленный MOSFET-преобразователь уровней. Делитель напряжения не подходит: он нарушает поведение выхода с открытым стоком в важном направлении.
Когда что-то идёт не так
| Симптом | Обычно |
|---|---|
| Сканер вообще ничего не находит | Нет подтягивающих резисторов, перепутаны SDA/SCL или отсутствует общая земля |
| С тремя платами работает, с четырьмя отказывает | Параллельные подтягивающие резисторы ниже предела по току |
| Устройства нет по адресу из технического описания | Указан 8-битный адрес; сдвиньте вправо на один разряд |
| Два одинаковых датчика, отвечает только один | Конфликт адресов — вывод установки адреса, XSHUT или мультиплексор |
| На коротком кабеле читает нормально, на длинном отказывает | Ёмкость шины; снизьте частоту или сократите трассу |
| Случайные повреждения при работе двигателей | Шум питания — см. питание и просадки |
| После сбоя сканер внезапно возвращает пустоту | Устройство зависло, удерживая SDA на низком уровне; подайте SCL девять раз |
| Работает отдельно, портит данные при загруженной шине | Контроллер не поддерживает растяжение тактовой частоты |
Полезная привычка — сначала каждый раз запускать сканер, до открытия исходников библиотеки. Это занимает тридцать секунд и делит проблему пополам — а половина всей отладки I²C состоит в незнании того, на какой стороне провода находится неисправность.
Исследуйте граф
Входит в эти сборки
Проекты и учебные пути, в которые входит это руководство.
Дополнительные материалы