В рамках изучения Verilog я выбрал для себя интересную и полезную задачу, которую изначально планировал решить в рамках цикла статей по Xilinx Zynq. На отладочной плате, на которую я делал обзор в предыдущих статьях, есть OLED дисплей SSD1306 который управляется по I2C. Я решил, что было бы круто вывести на него какую-нибудь информацию из Linux, например температуру или загрузку CPU. Но чтобы это сделать — полезной информации нужно пройти путь через от Userspace до I2C Master Controller который управляет SSD1306. И вот реализацию этого самого контроллера из этой связки я хотел бы описать в этом цикле статей.

И немного поразмыслив — я подумал, что на этапе разработки этого модуля быстрее было бы его реализовать плате с ПЛИС Altera. Уж очень долго собирается bitstream-файл под Zynq. А в качестве тестового подчиненного устройства — буду использовать EEPROM и по мере готовности задачи — потом просто перенесу модуль в Vivado.

В как раз о том, что такое I2C, как я реализовывал Master Controller для работы с подчиненным устройством, чем руководствовался и что получилось — я опишу для вас в этой и последующих статьях.

Традиционно, кому интересно — добро пожаловать под кат! =)

image

Дисклеймер. Перед началом повествования, хотелось бы заранее оговориться, что основная цель, которую я преследую при написании этой статьи — рассказать о своем опыте. Я не являюсь профессиональным разработчиком под ПЛИС на языке SystemVerilog и могу допускать какие-либо ошибки в использовании терминологии, использовать не самые оптимальные пути решения задач, etc. Но отмечу, что любая конструктивная и аргументированная критика только приветствуется. Что ж, поехали…

Постановка задачи


Итак. Основная задача, которая передо мной стоит — это вывести информацию из Linux на OLED-дисплей который расположен на плате Zynq Mini, который подключен к PL-части Zynq.

Чтобы решить эту задачу, мне, как новичку, нужно научиться очень многому и проделать очень много работы:

  • Сделать I2C Master Controller, который будет непосредственным связующим звеном между OLED-дисплеем и логикой в ПЛИС;
  • Сделать контроллер, который будет разгребать данные приходящие из Linux, складывать их в framebuffer и потом посылать их через I2C Controller в дисплей, а также инициализировать его, управлять им, реагировать на возможные ошибки и т.п.;
  • Связать логику в ПЛИС с драйвером в Linux;
  • Создать драйвер для Linux и прикладную программу которые будут формировать нужную мне информацию, преобразовывать ее в подходящий для вывода на дисплее формат и отсылать ее в ПЛИС.

Первым шагом я решил реализовать I2C Master Controller. Задача, которая стоит передо мной на этом этапе делится еще на несколько подзадач:

  • Познакомиться с I2C, разобраться как с ним работать и что он из себя представляет на физическом и логическом уровне;
  • Описать логику работы state-машины и спроектировать конечный автомат;
  • Протестировать и отладить полученный результат.

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

Итак. Кажется всё реализуемо, и не выглядит страшно, поэтому погнали, рассмотрим что же это такое, этот I2C на физическом уровне…

Что такое I2C и как он работает?


Прежде чем броситься в проектирование автомата состояний и написание HDL-кода — стоит для начала разобраться с тем, что такое I2C, зачем он нужен и как он вообще работает. Я не буду рассказывать о том, кто, как и зачем придумал этот интерфейс т.к. сути дела это не меняет — перейду сразу к рассмотрению характеристик и тонкостей касающихся принципов функционирования самого интерфейса.

Сделаю небольшую оговорку. В поисковиках можно найти предостаточно самых разнообразных материалов по интерфейсу I2C (он же IIC, он же TWI, он же I²С) и все они будут в той или иной степени об одном и том же. Но я решил попробовать расставить свои акценты, написать о том, что мне было интересно при изучении этого интерфейса, обобщить все самое интересное что мне удалось найти по этой теме и используя свои навыки написания статей сделать статью несколько особенной и выделяющейся на общем фоне. И еще важный момент — не стоит мою статью считать чем то оригинальным, или упаси боже, исчерпывающим руководством. По всем вопросам, которые не отражены в статье, я рекомендую в первую очередь обратиться к стандарту (спецификации) интерфейса I2C.

Итак. Коротко перечислю ключевые особенности этого интерфейса:

  • Очень популярный интерфейс, который используется для обмена данными между различными контроллерами, датчиками, сенсорами, запоминающими устройствами и т.п.;
  • Интерфейс синхронный, т. е. передача данных осуществляется под управлением синхронизирующего тактового сигнала;
  • Интерфейс низкоскоростной и в зависимости от конкретной версии стандарта и режима работы доступны скорости передачи данных 10, 100, 400 Кбит/c. С появлением новых редакций стандартов также стали доступны скорости в 1, 3.4 и 5 Мбит/c;
  • Интерфейс последовательный, т.е. каждый передаваемый бит идёт по очереди, друг за другом;
  • В интерфейсе используется модель передачи данных по схеме “ведущий — ведомый”, когда все устройства на шине имеют соответствующие роли и специфичное для этих ролей поведение;
  • Интерфейс двунаправленный, т. е. позволяет передавать данные как от Slave-устройства к Master, так и наоборот;
  • Интерфейс полудуплексный, т. е. данные в один момент времени могут идти только в одну сторону, либо от Master к Slave, либо наоборот;
  • Данные передаются порциями (пакетами) по 8 бит, с одним завершающим, 9-м битом подтверждения ACK/NACK.

А теперь, так же тезисно и по пунктам, я опишу общий принцип и особенности подключения устройств к шине. Для организации шины, чаще всего, используются напряжения 3.3 и и для передачи данных используется только два сигнальных проводника (“ GND” — не в счёт):

  • SDA т. е. Serial Data — для передачи бит данных;
  • SCL т. е. Serial Clock — для передачи тактовых сигналов.

В интерфейсе I2C, как я уже упомянул выше, существует распределение устройств по ролям и определено два вида ролей:

Master т. е. ведущий. Это устройство которое инициирует передачу данных, генерирует тактовый сигнал, взаимодействует со Slave-устройством и завершает передачу данных;

Slave т. е. подчиненный. Это устройство которое участвует в обмене данными с Master устройством.

Отдельно отмечу, что не стоит путать роли Master/Slave c ролями приемника и передатчика. И Master и Slave могут равнозначно как отправлять, так и принимать информацию.

Изначально предполагается наличие на шине, как минимум, одного Master-устройства и одного Slave-устройства. Отдельно нужно уточнить, что принцип подключения Master и Slave устройств к шине абсолютно одинаков. Так же стандарт I2C допускает наличие на шине нескольких Master-устройств.

Общий принцип коммуникации на I2C-интерфейсе является, по своей сути, сеансовым и выглядит следующим образом:

  • Master начинает “разговор” с устройствами на шине;
  • Master “проговаривает” адрес устройства с которым он хотел бы “поговорить”;
  • Master обозначает что он сейчас будет делать — читать или записывать;
  • Slave подтверждает свое наличие на шине;
  • Происходит обмен данными;
  • Master завершает передачу данных.

Любой сеанс передачи данных между устройствам на шине происходит только по их адресу. Но Master в этом случае не имеет своего адреса, который ему, к слову, ни к чему. Чаще всего мне приходилось сталкиваться с 7-битной адресацией устройств на шине и это говорит о том, можно подключить до 112 устройств (т. к. 16 адресов являются зарезервированными) на одну шину. Однако, по мере развития стандарта I2C, появилась возможность задействовать 10 битное адресное пространство и на одну шину стало возможно подключить больше 1000 устройств. Но реальное ограничение по количеству устройств определяется общей емкостью шины (об этом ниже).

Помимо ограничения общей емкости шины есть другое ограничение — на шину невозможно подключить несколько устройств с одним и тем же адресом. Такео может случиться если у этих устройств адрес задан аппаратно и не изменяется или нет ножек формирования последних бит адреса. В этом случае обычно задействуются дополнительные внешние устройства. Я не буду останавливаться на этой теме, поэтому идём дальше.

Физический уровень. Общий принцип


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

Итак, общий вид подключения устройств к шине выглядит следующим образом:

image

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

Рассмотрим типичный выходной инвертирующий каскад CMOS, он еще называется push-pull. Название выбрано, как по мне, не самое удачное, т.к. не подчеркивает низкоимпедансный характер соединений, управляющих выходом.

Логика его работы предельно проста. Если значение на входе равно логической единице, то P-канальный транзистор (сверху) закрыт, а N-канальный транзистор (снизу) открыт — и значение на выходе — логический ноль за счет получения низкоомного соединения с землей. И наоборот:

image

Но есть один нюанс, объединить такие логические схемы в шину не получится, потому что при определенном сочетании значений входных сигналов получается короткое замыкание:

image

И для решения этой проблемы, чтобы была возможность объединить сигналы на одной шине, была применена схема подключения open-drain, которая собственно и используется на сигнальных линиях интерфейса I2C:

image

В такой схеме P-канальный транзистор из схемы push-pull просто заменен внешним резистором и по логике зависимости входных и выходных сигналов получается тот же самый результат:

  1. Если подан высокий уровень на NMOS-транзистор — то потенциал линии притянется к земле и никаких коротких замыканий не возникнет т. к. ток идёт через резистор;
  2. Если на входе логический ноль — цепь размыкается и это означает, что выход как бы подключается к Vdd через внешний резистор.

Но у такого способа реализации шинного интерфейса есть несколько интересных нюансов.

Во-первых, в отличие от push-pull конфигурации, при логической единице, т.е. при открытии ключа N-канального транзистора возникает большое энергопотребление потому что возникает ток, который потечет через резистор, а потом через канал N-канального транзистора на землю. В push-pull конфигурации этот ток блокируется высоким сопротивлением выключенного P-канального транзистора.

Во-вторых — на линии будет всегда присутствовать единица, кроме случаев когда кто-то из устройств на шине не открыл N-канальный транзистор и не опустил логический уровень линии на ноль. Такая схема подключения называется “монтажное И”. Благодаря этому реализуется еще одна интересная особенность: любое устройство на шине может безопасно и принудительно установить низкий логический уровень на одной из линий, даже если другое устройство пытается сделать обратное. Это, кстати, основа функции “Clock synchronization” и “Clock stretching”, которую рассмотрим в следующей статье.

В-третьих — только такая конфигурация позволяет напрямую подключать два (или более) драйвера с открытым стоком (или коллектором) на одну шину: подтягивающий резистор гарантирует, что не будет короткого замыкания между Vdd и GND.

В общем случае, система установки значения текущего уровня на линии выглядит вот так:

image

Для фиксации значения сигнала и для передачи его на обработку в микросхему используется достаточно простая схема. Грубо говоря, перед N-канальным транзистором подключается логический буфер, который фиксирует все изменения на шине:

image

Если обобщить всё вышесказанное и изобразить полную схему подключения устройств к шине, с учетом всех необходимых элементов, то она будет выглядеть следующим образом:

image

Физический уровень. Режимы работы


Коротко перечислю режимы работы, которые поддерживает шина I2C, но без углубления в суть изменений от одного варианта к другому. Скажу лишь, что основные отличия всех режимов друг от друга заключаются в изменении скорости работы, частот тактирования и соответственно отличие временных характеристик цифровых сигналов, таких как время нарастания и спада фронта тактового сигнала, длительность логической единицы и нуля, ну и т. п.

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

Так же в более «скоростных» версиях стандарта и режимах работы повышены требования к реализации встроенных подавителей выбросов и шумов. Начиная с Fast Mode требуется наличие триггера Шмидта на обоих линиях, выходной буфер быстрых устройств должен иметь каскад с управлением временем заднего фронта линий SDA и SCL и прочие разные изменения на которых мы не будем останавливаться т. к. мы сконцентрированы только на Standart и Fast-режимах работы и за высокими скоростями пока идти рано.

image

Физический уровень. Подтягивающие резисторы и емкость шины


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

Первая роль, которую играют эти резисторы — это именно они обеспечивают возможность установки логической единицы на линиях передачи данных. Логическая единица будет всегда, по умолчанию, на входном буфере устройства который считывает текущее значение сигнала на линии. Логично утверждать, что если эти резисторы определяют одно из двух состояний линии — их наличие на шине обязательно. А исходя из этого можно сделать интересный вывод — получается, что передача и прием данных осуществляется по сути только опусканием линии в значение логического нуля, т. к. единица устанавливается сама, за счёт подтягивающих резисторов.

Вторая роль, которую играют эти резисторы — балансировка взаимоисключающих параметров энергопотребления и помехозащищенности. Чем меньше сопротивление резисторов, тем больше ток в сигнальных линиях — тем сигналы менее подвержены влиянию внешних факторов, и тем большую скорость можно обеспечить за счет более надежной передачи. Но если мы говорим об автономных устройствах — тут уже большой ток не допустим, по вполне понятным причинам. Поэтому стоит брать во внимание то, в каких условиях будет использоваться устройство, насколько вероятно возникновение помех на линии и насколько критично расходование энергии устройством.

Помимо помех есть еще один фактор, который упоминался выше — емкость шины. Сейчас объясню что это и как она влияет на сигналы на шине. В идеальном мире ожидается, что при работе интерфейса мы будем иметь прямоугольные импульсы при попеременном выставлении логических уровней и что все будет хорошо:

image

Но действительность и физика процесса вносит свои коррективы. Линии передачи данных, а именно дорожки на плате, кабели (в случае выноса устройства наружу), ножки микросхем, и прочие элементы электрических цепей — так или иначе не лишены паразитной емкости. И в реальности получим то, что я отразил на схеме:

image

Эти ёмкости появляются как между самими сигнальными проводниками, так и между линиями питания, между сигнальными проводниками и линиями питания и всем остальным что есть на плате.

Так что же в итоге оказывает влияние. Смотрите. Если мы хотим передать цифровой сигнал в виде нарастающего импульса, то при нарастании фронта сигнала заряжаются все эти ёмкости и в соответствии с формой заряда RC-цепи соответствующий сигнал попадет на считывающий буфер:

image

А при переходе сигнала к нулю — первым делом разряжаются все емкости, соответственно через устройство, открывшее транзистор и тем самым подтянувшее линию к нулю:

image

И чем больше суммарная паразитная емкость всех этих конденсаторов, тем сильнее будет искажаться крутизна фронтов и в лучшем случае, вместо ожидаемых прямоугольных импульсов, мы увидим примерно вот такую картину:

image

То есть по сути — мы имеем RC-цепи распределенные по всей шине, которые в данном случае являются фильтрующими, для тока высокой частоты (100 и 400 кГц). Логично предположить, что для того чтобы уменьшить влияние этих RC-цепей просто берем и уменьшаем сопротивление R, тем самым уменьшаем постоянную времени RC-цепи и всё будет хорошо. Но не всё так просто — от этого же увеличится ток, протекающий от Vdd на GND (через подтягивающий резистор) в момент когда SCL или SDA находятся в логическом нуле. Поэтому бесконтрольно снижать сопротивление нельзя, плюсом к этому есть риск того, что транзисторы могут не выдержать протекаемый через них ток и просто сгореть.

Другой интересный эффект. По мере наращивания количества устройств на шине или при изменении трассировки и характера соединения устройств на шине — может происходить неконтролируемое и неочевидное увеличение емкости шины, которое может привести к другому нежелательному эффекту — линия будет дольше восстанавливаться в единицу т.к. идет перезаряд паразитной емкости между проводами и от этого сильнее заваливаются фронты импульсов. И в определенный момент, если не регулировать значение сопротивления подтягивающих резисторов, может случиться так, что напряжение сигнала даже не достигнет в отведенное время достигнуть уровня фиксации логической единицы, ну или не будет оставаться на нем достаточно долго, чтобы быть зафиксированным. Плюсом стоит если учесть, что у разных цифровых микросхем разные пороги фиксации логического уровня, поэтому если не будем контролировать емкость шины — мы можем получить разнообразные спецэффекты, подобным тому что изображено ниже:

image

Значит получается, что вопрос учета емкости и правильности выбора сопротивления на подтягивающих резисторах — достаточно важен. Так какое же сопротивление выбрать? Давайте попробуем разобраться.

Всё же для начала нужно понимать, а какова текущая величина емкости шины. Конечно, если мы знаем емкость — то посчитать не сложно. А если нет? Самый очевидный способ узнать емкость шины — измерить. По крайней мере, это будет гораздо проще, чем пытаться выполнить точный расчет в котором будет учтен каждый источник емкости. Тем более такой рассчёт кажется непростой и трудоёмкой задачей — при конструировании электрических цепей образуется настолько невообразимое количество конденсаторов в самых разнообразных местах, что учесть их все кажется нереальным. Но если методы измерения и расчета не подходят (как это часто бывает), то можно сделать очень грубую оценку, с подключением осциллографа к шине, посмотреть на крутизну фронтов и приближенно посчитать емкость по времени нарастания фронта, как это делается в рассчётах RC-цепей.

Но допустим, мы все измерили и у нас емкость шины равна 50 пФ, и мы хотим соответствовать спецификации I2C Standard Mode, в которой указано, что время нарастания восходящего фронта должно быть 1000 нс. Если вспомнить формулы расчета (или если открыть онлайн калькуляторы ????) характеристик RC-цепей, то чтобы рассчитать сопротивление подтягивающих резисторов для такой емкости шины и для такого времени нарастания потребуется сделать несложные вычисления:

image

Если посмотреть в спецификацию I2C Fast Mode — то там уже время нарастания импульса 300 нс. И получается уже немного другой расчет. Требуется уменьшать сопротивление резистора:

image

Соответственно, в зависимости от используемого режима работы — необходимо выбирать соответствующий номинал сопротивлений подтягивающих резисторов.

А теперь обратим внимание на скорость работы (частоту). Как я показал выше — сигнал I2C имеет форму меандра и если мы знаем время нарастания импульса то исходя из требований спецификации I2C можно посчитать, какую максимальную частоту можно получить. Standard Mode определяет время длительности нахождения тактового импульса в значении логической единицы — минимум 4000 нс. что в четыре раза больше времени нарастания импульса, и если грубо откинуть остальные параметры то получится следующее:

image

Для I2C Fast Mode время длительности тактового импульса в значении логической единицы составляет минимум 0.6 мкс, что судя по спецификации в 2 раза больше чем время нарастания импульса:

image

Поэтому можно сделать вывод для Standart Mode — будет достаточно 20kΩ, а для Fast Mode — 6kΩ. Но если вдруг частота 125 или 833 кГц недостаточно высока для ваших целей — можно снижать сопротивление подтягивающих резисторов (естесственно, за счет увеличения энергопотребления) до тех пор, пока не будет обеспечены условия для корректной работы на требуемой частоте.

Предвосхищая возгласы профессионалов сразу же оговорюсь — это всё, конечно же, упрощенные и приблизительные расчеты, в которых не учтена разница у времени длительности импульса для нуля и единицы, не учтено время спада фронта и многое другое — но, могу порадовать вас тем, что I2C-интерфейс не настолько чувствителен к строгой реализации требований спецификации. И, честно говоря, не стоит сильно напрягаться, чтобы найти идеальное сопротивление т. к. микросхемы достаточно стабильно работают даже при существенных отклонениях в действительных значениях времени нарастания и спада импульса.

Но специально для щепетильных большинство производителей в даташитах указывают простые графики, которые могут помочь определиться с выбором номиналов сопротивлений и будет достаточно остановиться на этом.

А теперь ради интереса давайте возьмем очень распространеный вариант, который чаще всего используют в большинстве вариантов различных I2C-модулей, сенсоров и прочих — резисторы с номиналом в 4.7kΩ. Если посчитать длительность нарастания импульса для Standart и Fast Mode при сопротивлении в 4.7kΩ, то получим следующие значения:

image

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

Почитать подробнее можно тут...
  1. Внезапно, при гуглеже того как происходит рассчёт величин сопротивлений для резисторов подтяжки — я обнаружил ОФИГЕННЫЙ перевод статьи, на основе которой я составлял рассказ о физических процессах на шине. Помимо этого — у автора добавлено много интересного от себя в дополнение. Жаль, что данная статья не нагуглилась раньше, чем я сделал перевод нужного мне кусочка темы и добавил его в свой материал. Поэтому считаю благим делом поделиться ей хотя бы с вами тут: kmpu.ru/other/bus_i2c/index.html
  2. Оригинал материала про физические процессы в шине: www.allaboutcircuits.com/technical-articles/introduction-to-the-i2c-bus
  3. Её продолжение: www.allaboutcircuits.com/technical-articles/the-i2c-bus-hardware-implementation-details


Физический уровень. Помехи и проблемы при работе интерфейса


В завершение рассказа о физическом уровне — отдельно стоит отметить, что при работе I2C-интерфейса при определенных условиях кое-что может пойти не так:

  • Подтяжка на шине должна быть осуществлена к напряжению, на который рассчитаны конкретные GPIO или пины используемого контроллера, иначе может произойти “исход магического дыма” и Slave-устройство помрёт (и возможно Master тоже);
  • Если вдруг решили снижать значение сопротивления подтягивающих резисторов — не забудьте про максимальное ограничение тока стока выходного транзистора;
  • Ни в коем случае, в готовом устройстве, нельзя переключать вывод SDA или SDL в режим GPIO Output т. к. достаточно просто получить короткое замыкание на линии;
  • Не стоит забывать, что в I2C существуют перекрестные наводки сигнала SCL на линию SDA и наоборот (как в банальном трансформаторе). В условиях, когда Master и Slave расположены на одной плате — вероятность возникновения таких проблем минимальна. Но если мы имеем дело с выносными устройствами — можно словить эти эффекты. Подробно я описывать эти эффекты я не буду, т. к. это выходит за рамки этой статьи, но я предлагаю об этом почитать самостоятельно тут и тут.

Физический уровень. Плюсы и минусы интерфейса


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

Плюсы:

  • Используется только две линии: данные и тактирование, соответственно проще трассировать будущее устройство;
  • При такой простоте подключения можно включать и выключать устройство с шины практически “на горячую” т. к. в устройствах предусмотрен специальный фильтр различных шумов и всплесков;
  • I2C-совместимые устройства имеют такое устройство интерфейса, которое позволяет осуществлять передачу данных даже если у них существенно отличается напряжение питания (при условии корректного выбора напряжения для подтяжки линий);
  • Интерфейс низкоскоростной, а значит выше гарантия того, что данные будут переданы без повреждений и меньше влияния внешней среды на передаваемые данные;
  • Имеется возможность использовать на шине несколько Master-устройств с реализованным в I2C-интерфейсе механизмом арбитража и разруливания коллизий;
  • Не требуется внешних дешифраторов адреса и любой другой внешней логики для реализации обмена данными.

Минусы:

Используется только для передачи данных в рамках одного устройства;

  • Необходимы подтягивающие резисторы, которые ограничивают частоту тактирования и влияют на общее энергопотребление устройства;
  • Интерфейс очень чувствителен к перекрестным помехам между линиями SDA, SCL;
  • Строго ограниченная емкость по количеству устройств;
  • Необходимо учитывать общую величину подтяжки линий для всех подключенных к шине устройств и по сути корректировать ее при добавлении\удалении устройств;
  • Есть опасность получить КЗ при неправильном конфигурировании выводов;
  • Ограниченность количества одинаковых устройств на одной шине;
  • Всё-таки не такая большая скорость передачи данных;
  • Сложность диагностики при наступлении каких-либо проблем с подчиненными устройствами.

Заключение


Итак, разобравшись с физическими основами и принципами устройства интерфейса I2C теперь можно в полной мере осознать все тонкости и принцип функционирования интерфейса, что от чего зависит, куда можно будет копнуть в случае если что-то пойдет не так.

Не стал раздувать из статьи лонг-рид и решил рассмотреть протокольные особенности в следующей статье: перейдем на уровень логики обмена данными, рассмотрим как организуются сеансы связи, как формируются пакеты, служебные сигналы и потом из этого всего, что изучили — составим целостную диаграмму состояний на основании которой можно будет переходить к проектированию конечного автомата.

До встречи в следующей статье! ????



Возможно, захочется почитать и это:


Комментарии (10)


  1. dlinyj
    26.07.2023 08:05
    +5

    Ух! Вот это да, вот это хабротортно. Спасибо большое!


    1. megalloid Автор
      26.07.2023 08:05
      +1

      Спасибо, рад писать для Вас!)

      Дальше будет поинтереснее материал)


  1. KeisN13
    26.07.2023 08:05
    +1

    Судя по статьям автора Линукс -> Обзор отладок -> Верилог -> Физика протокола в скором времени стоит ожидать появление теории квантовой механики с последующим описанием SPI протокола на верилоге :)


    1. megalloid Автор
      26.07.2023 08:05
      +4

      :D не-не-не, идём по строгому плану повествования

      У меня еще по тестированию БП трек притормозился, жду прибор))


  1. nikolz
    26.07.2023 08:05

    По-моему, у Вас ошибка в терминологии.

    То, что Вы называете "временем нарастания", называется "постоянной времени нарастания"=RC.

    А "временем нарастания" называется величина K*RC, где K-константа от 2 до 5.

    Вы берете 2 и 4. Я привык брать 3. Но это не принципиально.


    1. garus_ru
      26.07.2023 08:05
      +2

      Погодите, что за магические числа...

      Если "время нарастания" это изменение сигнала от 0,1 до 0,9 от его значения, то резисторы автор тоже неправильно считает - у него в расчете всего лишь 1*тау (одно тау, где тау=R*C), а это не до 0.9, а до 0.63 от номинального.

      А ваши 3*тау как раз хороши - 0,95


  1. checkpoint
    26.07.2023 08:05
    +3

    А Verilog то где ? Как раз хотел посмотреть как автор реализует двунаправленность линии SDA.


    1. megalloid Автор
      26.07.2023 08:05

      Будет дальше, не стал лонгрид раздувать)


      1. checkpoint
        26.07.2023 08:05
        +2

        А вот зря. Ладно, подождем следующей части.


  1. AlexanderS
    26.07.2023 08:05

    На внешних резисторах иногда экономят делая подтяжку pull-up внутри ПЛИСа. Такой подход может быть даже оправданным в рамках одного законченного устройства, в котором шина уже меняться не будет.