Шина i2c и как ее использовать

Шина I2C. Основные понятия

В данной статье рассматриваются основные характеристики и преимущества протокола последовательной связи I2C (Inter-Integrated Circuit).

Связь через алфавитную кашу

Неудивительно, что общей особенностью электронных систем является необходимость обмена информацией между двумя или тремя или десятью отдельными компонентами. Инженеры разработали ряд стандартных протоколов, которые помогают различным микросхемам успешно общаться, что становится очевидным, когда вы сталкиваетесь с потоком сокращений в разделе «Связь» в списке характеристик микроконтроллера или сигнального процессора: UART, USART, SPI, I2C, CAN. Каждый протокол имеет свои плюсы и минусы, и важно немного знать о каждом из них, чтобы вы могли принимать обоснованные решения при выборе компонентов или интерфейсов.

Эта статья посвящена шине I2C, которая обычно используется для связи между отдельными интегральными микросхемами, расположенными на одной печатной плате. Два других распространенных протокола, которые также входят в эту основную категорию – это UART (универсальный асинхронный приемник/передатчик) и SPI (последовательный периферийный интерфейс). Вам необходимо знать основные характеристики I2C, прежде чем вы сможете полностью понять сравнение этих трех интерфейсов, поэтому обсудим эту тему в конце статьи.

Много названий, а шина одна

Дополнительная путаница вносится, когда вы замечаете, что SMB или SMBus явно используется в качестве еще одного способа обращения к шине I2C. Фактически эти сокращения относятся к шине управления системой SMB (System Management Bus), которая отличается, хотя и почти идентична, от шины I2C. Оригинальный протокол I2C был разработан компанией Phillips Semiconductor, а спустя годы Intel определил протокол SMBus как расширение I2C. Эти две шины в значительной степени взаимозаменяемы; если вас интересуют незначительные отличия между ними, то смотрите страницу 57 спецификации шины управления системой SMB.

Выглядит, как попытка обсудить что-то важное в комнате, полной людей.

Чтобы оценить ловкие технические приемы, которые делают I2C настолько эффективной, вам нужно подумать о трудностях достижения надежной, но универсальной связи между несколькими независимыми компонентами. Ситуация достаточно проста, если у вас есть одна микросхема, которая всегда является ведущей (master), и одна микросхема, которая всегда является ведомой (slave). Но что, если у вас есть несколько ведомых? Что если ведомые не знают, кто ведущий? Что, если у вас есть несколько ведущих? Что произойдет, если ведущий запросит данные у ведомого устройства, которое по какой-то причине перестало функционировать? Или что, если ведомый перестал функционировать в середине передачи? Что делать, если ведущий утверждает, что шина осуществляет передачу, а затем он выйдет из строя, прежде чем освободить шину?

0c9d6ff3e160a35c72bd72f6bd91f60fde3285a6 Возможные проблемы на шине

Дело в том, что в системе связи такого типа есть много вещей, которые могут пойти не так. Вы должны помнить об этом, когда будете изучать I2C, потому что в противном случае этот протокол будет казаться невыносимо сложным и перегруженным. Дело в том, что эта дополнительная сложность – это то, что позволяет I2C обеспечивать гибкую, расширяемую, надежную и низкоуровневую последовательную связь.

Обзор

Прежде чем вдаваться в детали, давайте рассмотрим ключевые характеристики I2C:

I2C против UART и SPI

Преимущества I2C можно резюмировать следующим образом:

А вот некоторые недостатки:

С этих точек зрения видно, что I2C особенно подходит, когда у вас сложная, разнообразная или обширная сеть связанных устройств. Интерфейсы UART обычно используются для соединений «точка-точка», потому что не имеют стандартного способа адресации различных устройств и совместного использования линий связи. SPI отлично работает, когда у вас есть одно ведущее и несколько ведомых устройств, но для каждого ведомого устройства требуется отдельный сигнал выбора ведомого, что приводит к большому количеству линий связи и к трудностям разводки печатной платы, когда на шине находится много устройств. И SPI неудобен, когда вам нужно поддерживать несколько ведущих устройств.

Возможно, вам придется сознательно избегать I2C, если пропускная способность является приоритетом; SPI поддерживает более высокие частоты тактового сигнала и минимизирует накладные расходы. Кроме того, разработка низкоуровнего аппаратного обеспечения для SPI (или UART) намного проще, поэтому, если вы работаете с FPGA и разрабатываете свой последовательный интерфейс с нуля, I2C, вероятно, стоит выбирать последним.

Заключение

Мы рассмотрели основные характеристики I2C, и теперь мы достаточно хорошо знаем о преимуществах и недостатках этого протокола, чтобы принять обоснованное решение о том, какую последовательную шину выбрать для какого-то конкретного приложения. В будущих статьях мы рассмотрим протокол и как его реализовать более подробно.

Источник

Подробное описание интерфейса I2C

Интерфейс I2C (или по другому IIC) — это достаточно широко распространённый сетевой последовательный интерфейс, придуманный фирмой Philips и завоевавший популярность относительно высокой скоростью передачи данных (обычно до 100 кбит/с, в современных микросхемах до 400 кбит/с), дешевизной и простотой реализации.

i2c 1

Физически сеть представляет собой двухпроводную шину, линии которой называются DATA и CLOCK (необходим ещё и третий провод — земля, но интерфейс принято называть двухпроводным по количеству сигнальных проводов). Соответственно, по линии DATA передаются данные, линия CLOCK служит для тактирования. К шине может быть подключено до 128 абонентов, каждый со своим уникальным номером. В каждый момент времени информация передаётся только одним абонентом и только в одну сторону.

Читайте также:  Чертеж транспортира для установки фаз грм

Устройства I2C имеют выход с «открытым коллектором». Когда выходной транзистор закрыт — на соответствующей линии через внешний подтягивающий резистор устанавливается высокий уровень, когда выходной транзистор открыт — он притягивает соответствующую линию к земле и на ней устанавливается низкий уровень (смотрите рисунок). Резисторы имеют номинал от нескольких килоОм до нескольких десятков килоОм (чем выше скорость — тем меньше номинал резисторов, но больше энергопотребление). На рисунке треугольниками на входе показано, что входы высокоомные и, соответственно, влияния на уровни сигналов на линиях они не оказывают, а только «считывают» эти уровни. Обычно используются уровни 5В или 3,3В.

Любое устройство на шине I2C может быть одного из двух типов: Master (ведущий) или Slave (ведомый). Обмен данными происходит сеансами. «Мастер»-устройство полностью управляет сеансом: инициирует сеанс обмена данными, управляет передачей, подавая тактовые импульсы на линию Clock, и завершает сеанс.

Кроме этого, в зависимости от направления передачи данных и «Мастер» и «Слэйв»-устройства могут быть «Приёмниками» или «Передатчиками». Когда «Мастер» принимает данные от «Слэйва» — он является «Приёмником», а «Слэйв» — «Передатчиком». Когда же «Слэйв» принимает данные от «Мастера», то он уже является «Приёмником», а «Мастер» в этом случае является «Передатчиком».

Не надо путать тип устройства «Мастер» со статусом «Передатчика». Несмотря на то, что при чтении «Мастером» информации из «Слэйва», последний выставляет данные на шину Data, делает он это только тогда, когда «Мастер» ему это разрешит, установкой соответствующего уровня на линии Clock. Так что, хотя «Слэйв» в этом случае и управляет шиной Data, — самим обменом всё равно управляет «Мастер».

В режиме ожидания (когда не идёт сеанс обмена данными) обе сигнальные линии (Data и Clock) находятся в состоянии высокого уровня (притянуты к питанию).

Каждый сеанс обмена начинается с подачи «Мастером» так называемого Start-условия. «Старт-условие» — это изменение уровня на линии Data с высокого на низкий при наличии высокого уровня на линии Clock.

После подачи «Старт-условия» первым делом «Мастер» должен сказать с кем он хочет пообщаться и указать, что именно он хочет — передавать данные в устройство или читать их из него. Для этого он выдаёт на шину 7-ми битный адрес «Слэйв» устройства (по другому говорят: «адресует «Слэйв» устройство»), с которым хочет общаться, и один бит, указывающий направление передачи данных (0 — если от «Мастера» к «Слэйву» и 1 — если от «Слэйва» к «Мастеру»). Первый байт после подачи «Старт»-условия всегда всеми «Слэйвами» воспринимается как адресация.

Поскольку направление передачи данных указывается при открытии сеанса вместе с адресацией устройства, то для того, чтобы изменить это направление, необходимо открывать ещё один сеанс (снова подавать «Старт»-условие, адресовать это же устройство и указывать новое направление передачи).

После того, как «Мастер» скажет, к кому именно он обращается и укажет направление передачи данных, — начинается собственно передача: «Мастер» выдаёт на шину данные для «Слэйва» или получает их от него. Эта часть обмена (какие именно данные и в каком порядке «Мастер» должен выдавать на шину, чтобы устройство его поняло и сделало то, что ему нужно) уже определяется каждым конкретным устройством.

Заканчивается каждый сеанс обмена подачей «Мастером» так называемого Stop-условия, которое заключается в изменении уровня на линии Data с низкого на высокий, опять же при наличии высокого уровня на линии Clock. Если на шине сформировано Stop-условие, то закрываются все открытые сеансы обмена.

Внутри сеанса любые изменения на линии Data при наличии высокого уровня на линии Clock запрещены, поскольку в это время происходит считывание данных «Приёмником». Если такие изменения произойдут, то они в любом случае будут восприняты либо как «Старт»-условие (что вызовет прекращение обмена данными), либо как «Стоп»-условие (что будет означать окончание текущего сеанса обмена). Соответственно, во время сеанса обмена установка данных «Передатчиком» (выставление нужного уровня на линии Data) может происходить
только при низком уровне на линии Clock.

Несколько слов по поводу того, в чём в данном случае разница между «прекращением обмена данными» и «окончанием сеанса обмена». В принципе «Мастеру» разрешается, не закрыв первый сеанс обмена, открыть ещё один или несколько сеансов обмена с этим же (например, как было сказано выше, для изменения направления передачи данных) или даже с другими «Слэйвами», подав новое «Старт»-условие без подачи «Стоп»-условия для закрытия предыдущего сеанса. Управлять линией Data, для того, чтобы отвечать «Мастеру», в этом случае будет разрешено тому устройству, к которому «Мастер» обратился последним, однако старый сеанс при этом нельзя считать законченным. И вот почему. Многие устройства (например те же eeprom-ки 24Схх) для ускорения работы складывают данные, полученные от «Мастера» в буфер, а разбираться с этими полученными данными начинают только после получения сигнала об окончании сеанса обмена (то есть «Стоп-условия»).

То есть, например, если на шине висит 2 микросхемы eeprom 24Cxx и вы открыли сеанс записи в одну микросхему и передали ей данные для записи, а потом, не закрывая этот первый сеанс, открыли новый сеанс для записи в другую микросхему, то реальная запись и в первую и во вторую микросхему произойдёт только после формирования на шине «Стоп-условия», которое закроет оба сеанса. После получения данных от «Мастера» eeprom-ка складывает их во внутренний буфер и ждёт окончания сеанса, для того, чтобы начать собственно процесс записи из своего внутреннего буфера непосредственно в eeprom. То есть, если вы после после передачи данных для записи в первую микруху не закрыли этот сеанс, открыли второй сеанс и отправили данные для записи во вторую микруху, а потом, не сформировав «Стоп-условие», выключили питание, то реально данные не запишутся ни в первую микросхему, ни во вторую. Или, например, если вы пишете данные попеременно в две микрухи, то в принципе вы можете открыть один сеанс для записи в первую, потом другой сеанс для записи во вторую, потом третий сеанс для записи опять в первую и т.д., но если вы не будете закрывать эти сеансы, то в конце концов это приведёт к переполнению внутренних буферов и в итоге к потере данных.

Читайте также:  Шаровый кран отопителя ваз 21099

Здесь можно привести такую аналогию: ученики в классе («слэйвы») и учитель («мастер»). Допустим учитель вызвал какого-то ученика (пусть будет Вася) к доске и попросил его решить какой-то пример. После того как Вася этот пример решил, учитель вызвал к доске Петю и начал спрашивать у него домашнее задание, но Васю на место не отпустил. Вот в этом случае вроде бы разговор с Васей закончен, — учитель разговаривает с Петей, но Вася стоит у доски и не может спокойно заниматься своими делами (сеанс общения с ним не закрыт).

В случае, если «Слэйв» во время сеанса обмена не успевает обрабатывать данные, — он может растягивать процесс обмена, удерживая линию Clock в состоянии низкого уровня, поэтому «Мастер» должен проверять возврат линии Clock к высокому уровню после того, как он её отпустит. Хотелось бы подчеркнуть, что не стоит путать состояние, когда «Слэйв» не успевает принимать или посылать данные, с состоянием, когда он просто занят обработкой данных, полученных в результате сеанса обмена. В первом случае (во время обмена данными) он может растягивать обмен, удерживая линию Clock, а во втором случае (когда сеанс обмена с ним закончен) он никакие линии трогать не имеет права. В последнем случае он просто не будет отвечать на «обращение» к нему от «Мастера».

Внутри сеанса передача состоит из пакетов по девять бит, передаваемых в обычной положительной логике (то есть высокий уровень — это 1, а низкий уровень — это 0). Из них 8 бит передаёт «Передатчик» «Приёмнику», а последний девятый бит передаёт «Приёмник» «Передатчику». Биты в пакете передаются старшим битом вперёд. Последний, девятый бит называется битом подтверждения ACK (от английского слова acknowledge — подтверждение). Он передаётся в инвертированном виде, то есть 0 на линии соответствует наличию бита подтверждения, а 1 — его отсутствию. Бит подтверждения может сигнализировать как об отсутствии или занятости устройства (если он не установился при адресации), так и о том, что «Приёмник» хочет закончить передачу или о том, что команда, посланная «Мастером», не выполнена.

Каждый бит передаётся за один такт. Та половина такта, во время которой на линии Clock установлен низкий уровень, используется для установки бита данных на шину передающим абонентом (если предыдущий бит передавал другой абонент, то он в это время должен отпустить шину данных). Та половина такта, во время которой на линии Clock установлен высокий уровень, используется принимающим абонентом для считывания установленного значения бита с шины данных.

Вот собственно и всё. На рисунках ниже всё это описание показано в графической форме.

3) Диаграммы и тайминги.

i2c 2
i2c 3

Параметр Обозн. Мин.знач. Комментарий
Свободная шина tBUF 4,7 мкс это минимальное время, в течении которого обе линии должны находиться в свободном состоянии перед подачей «Старт»-условия
Фиксация
«Старт»- условия
tHD;STA 4,0 мкс минимальное время от подачи «Старт»- условия до начала первого такта передачи
Готовность
«Стоп»- условия
tSU;STO 4,0 мкс минимальное время, через которое можно подавать «Стоп»- условие после освобождения шины Clock
Длительность LOW полупер. шины Clock tLOW 4,7 мкс минимальная длительность полупериода установки данных (когда на шине Clock низкий уровень)
Длительность HIGH полупер. шины Clock tHIGH 4,0 мкс минимальная длительность полупериода считывания данных (когда на шине Clock высокий уровень)
Удержание данных tHD;DAT то есть данные на шину Data можно выставлять сразу после спада на линии Clock
Готовность данных tSU;DAT 250 нс то есть поднимать уровень на шине Clock можно не ранее 250 нс после установки данных на шине Data

Минимальные значения времени в таблице указаны для максимальной скорости передачи 100 кбит/с.

Программная реализация мастер-абонента шины I2C в режиме single-master, библиотеки процедур: для PIC, для AVR

Программа для устройства копирования микросхем памяти 24Cxx (здесь можно посмотреть пример использования приведённых выше библиотек для реализации режима I2C-Master на PIC-контроллере)

Программа 2 для контроллера I2C-шлюза, режим Slave из терминалки ПК (а тут посмотреть пример того, как можно сделать I2C-Slave на контроллере AVR)

Читайте также:  Устройство прямоточного глушителя remus

Источник

Интерфейс I2C и Arduino

Инструкция по использованию протокола I 2 C совместно с Arduino

Нам понадобится:

1 Описание интерфейса I2C

Последовательный протокол обмена данными IIC (также называемый I2C – Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock). Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.

В сети есть хотя бы одно ведущее устройство (Master), которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».

1 Описание интерфейса I2C

Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.

Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства, с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 2 7 = 128 минус нулевой адрес). Следующий бит посылки – это код операции (чтение или запись) и ещё один бит – бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.

Это проиллюстрировано на рисунке ниже. Задача такая: подключиться к ведомому устройству с адресом 0x27 и передать ему строку «SOLTAU.RU». В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.

i2c timing wo Попытка мастера установить соединение с ведомым по I2C

Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит – бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.

i2c timing Временная диаграмма обмена по протоколу I2C

2 Реализация I2Cв Arduino

Arduino использует для работы по интерфейсу I2C два порта. Например, в Arduino UNO и Arduino Nano аналоговый порт A4 соответствует SDA, аналоговый порт A5 соответствует SCL.

2 Реализация I2C в Arduino UNO и Nano

Для других моделей плат соответствие выводов такое:

Плата Пин SDA Пин SCL
Arduino Uno, Nano, Pro и Pro Mini A4 A5
Arduino Mega 20 21
Arduino Leonardo 2 3
Arduino Due 20, SDA1 21, SCL1

3 Библиотека «Wire» для работы с IIC

Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire. Она имеет следующие функции:

Функция Назначение
begin(address) инициализация библиотеки и подключение к шине I2C; если не указан адрес, то присоединённое устройство считается ведущим; используется 7-битная адресация;
requestFrom() используется ведущим устройством для запроса определённого количества байтов от ведомого;
beginTransmission(address) начало передачи данных к ведомому устройству по определённому адресу;
endTransmission() прекращение передачи данных ведомому;
write() запись данных от ведомого в ответ на запрос;
available() возвращает количество байт информации, доступных для приёма от ведомого;
read() чтение байта, переданного от ведомого ведущему или от ведущего ведомому;
onReceive() указывает на функцию, которая должна быть вызвана, когда ведомое устройство получит передачу от ведущего;
onRequest() указывает на функцию, которая должна быть вызвана, когда ведущее устройство получит передачу от ведомого.

4 Подключение I2C устройствак Arduino

Давайте посмотрим, как работать с шиной I2C с помощью Arduino.

Сначала соберём схему, как на рисунке. Будем управлять яркостью светодиода, используя цифровой 64-позиционный потенциометр AD5171 (см. техническое описание), который подключается к шине I2C. Адрес, по которому мы будем обращаться к потенциометру – 0x2c (44 в десятичной системе).

4 Подключение цифрового потенциометра к Arduino по шине I2C

5 Управление устройством по шине IIC

Рассмотрим диаграммы информационного обмена с цифровым потенциометром AD5171, представленные в техническом описании:

diag Рассмотрим диаграммы чтения и записи цифрового потенциометра AD5171

Нас тут интересует диаграмма записи данных в регистр RDAC. Этот регистр используется для управления сопротивлением потенциометра.

Откроем из примеров библиотеки «Wire» скетч: Файл Образцы Wire digital_potentiometer. Загрузим его в память Arduino.

После включения вы видите, как яркость светодиода циклически нарастает, а потом гаснет. При этом мы управляем потенциометром с помощью Arduino по шине I2C.

По ссылкам внизу статьи, в разделе похожих материалов (по тегу), можно найти дополнительные примеры взаимодействия с различными устройствами по интерфейсу IIC, в том числе примеры чтения и записи.

6 Дополнительно о шине I2C

Доступно и интересно рассказывает о шине I2C Джереми Блюм в своём видео:

Источник

Оцените статью
Adblock
detector