Интерфейсная микросхема поддерживает работу с интерфейсом I2C (не путать с I2S!) в режиме MPSSE (Multi-Protocol Synchronous Serial Engine). Кроме I2C данный режим поддерживает целый перечень стандартных последовательных интерфейсов, таких как SPI, JTAG и т. п. Есть возможность реализации собственных интерфейсов в случае необходимости. Данное описание рассказывает о ряде нюансов поддержки интерфейса I2C, а так же дает повод поболтать на смежную тематику.
Дисклэймер: данная статья написана по рабочим материалам и в первую очередь предназначена для автора статьи, когда он потеряет оригинальный документ. В то же время, информация приведенная ниже может быть интересна и узкому кругу специалистов. Не рекомендуется для прочтения широкому кругу читателей кроме случаев, когда тот самый читатель хочет ненадолго погрузиться в мир отладки программно-аппаратных средств. Исследования проводились более года назад, однако указанная информация остается актуальной и в настоящий момент, поскольку библиотеки на сайте производителя не обновлялись. Информация об обнаруженных проблемах отправлялась производителю, однако никакой обратной связи не последовало. Написан пост по мотивам вот этого, за который автору выражается отдельная благодарность
Поддерживается независимая работа двух каналов I2C (один канал для FT232H). Пример схемы включения приведен в AN113 — в качестве примера используется коммуникация между FT2232H и микросхемой энергонезависимой памяти 24LC256. Непосредственно к интерфейсу I2C относятся только два сигнала: SCL (тактовый сигнал, на рисунке обозван SCC) и SDA (передаваемые данные). Согласно спецификации, каждый из этих сигналов может быть двунаправленным, однако часто на шине присутствует только одно ведущее устройство (мастер) и именно оно и задает тактовый сигнал. Данные в любом случае двунапраленные — на каждые 8 бит передаваемых данных следует 1 бит подтверждения.
На программном уровне работа с шиной I2C возможна двумя способами:
- Непосредственно через драйвер D2XX. В этом случае необходимо производить ручное программирование режима MPSSE в соответствии с набором команд, описанных в AN108. Вся работа идет через функции FT_Read() и FT_Write(), а так же сопутствующие функции открытия/закрытия устройства и т.п.
- С использованием библиотеки LibMPSSE-I2C. Данная библиотека решает все вопросы программирования режима MPSSE и позволяет производить операции чтения и записи указанного числа байт по шине I2C с использованием вызовов I2C_DeviceWrite() и I2C_DeviceRead(). Описание библиотеки приведено в AN177.
Исследования проводились с использованием одной из имеющихся плат. В качестве ведомого устройства на шине I2C использовался измеритель мощности INA219. Поскольку плата была взята та, что оказалась под рукой, между микросхемами FT2232H и INA219 оказалась FPGA (как мне повезло я понял несколько позже). Изначально я планировал ее использовать только для преобразование 3-х проводного интерфейса FT2232H в двухпроводной интерфейс шины I2C — в нормальном устройстве подобное преобразование происходит за счет схемы, см. рисунок выше.
Как уже писалось, при передаче данных на каждые 8 бит передаваемой информации следует подтверждение (ACK) – перевод сигнала в состояние 0 со стороны принимающего устройства. Если передающее устройство видит это подтверждение — значит его услышали и можно продолжать дальше. Если подтверждения нет — значит продолжать дальше бесполезно и обмен можно прекращать.
В процессе исследований было установлено, что библиотека LibMPSSE-I2C имеет ошибку, блокирующую возможность чтения более чем одного байта по шине в большинстве случаев. Ошибка проявляется возникновением глитча на тактовом сигнале перед выставлением подтверждения ACK о первом прочитанном байте со стороны FT2232H на шину. Длина глитча составляет 1 период частоты 12 МГц (порядка 8 нс). Данный глитч воспринимается слэйв-устройством на шине как тактовый сигнал, появляющийся в тот момент, когда признак ACK еще не установлен. После этого слэйв-устройство прерывает транзакцию. Пример подобной транзакции, в рамках которой происходит попытка чтения двух байт из устройства, показан на рисунках (захват данных производился на частоте 120 МГц, глитч присутствует на временных отсчетах 20968-20967). Временные диаграммы получены с использованием встраиваемого логического анализатора SignalTap для альтеровских FPGA (здесь я первый раз порадовался затесавшейся FPGA). На картинках видно, что по линии DI читается первый байт из устройства, далее устройство отваливается (получив некорректное подтверждение от мастера) и вместо второго байта читается 0xFF.
Читайте также: Шины переходные для ва5735
В случае фильтрации данного импульса обеспечивалась правильная процедура чтения по шине. В тестовом окружении фильтрация производилась на FPGA цифровым способом (был написан небольшой модуль на VHDL, отбрасывающий глитчи на входных сигналах). Другой возможный способ — фильтрация с использованием RC-цепочки на шине SCL, однако это ограничит максимальную частоту шины (в виду некоторой маразматичности, глубоко данное решение не анализировалось). Пример успешной транзакции (при условии фильтрации глитча) приведен на следующем рисунке. Теперь по шине DI мы видим корректное чтение двух байт.
Естественно, что хочется добраться до истинных причин такого поведения. К сожалению, исходные коды библиотеки LibMPSSE-I2C недоступны, дизассемблирование бинарников — не наша специализация. Но проанализировать обмен данными по USB при наличии открытого описания протокола — дело 5 минут. Ну часа. Ну уж никак не больше дня.
Детальное исследование показало проблему в формировании команд для контроллера MPSSE, формируемого библиотекой LibMPSSE-I2C. Далее приводится набор команд используемых для чтения 2х байт по шине (стоп-бит в конце не выставляется). Выделенные команды показывают место проблемы и способ решения (запрет перехода в 1 либо изменение фазы подаваемого тактового сигнала для признака ACK):
Видео:Лекция 308. Шина I2CСкачать
Шина I2C. Подробности аппаратной реализации
Основная информация для понимания и проектирования аппаратного обеспечения, необходимого для шины I2C.
Видео:Микросхемы и программаторы, Шины I2C и SPIСкачать
Дополнительная информация
Видео:Логический анализатор шины i2cСкачать
Иногда небольшое усложнение – это хорошо
Протокол I2C отличается некоторыми непростыми особенностями: вы не просто соединяете выводы нескольких микросхем вместе, а затем позволяете низкоуровневым аппаратным средствам брать управление на себя, пока вы читаете или записываете в соответствующий буфер, как это примерно происходит в случаях с SPI (последовательным периферийным интерфейсом) и UART (универсальным асинхронным приемником/передатчиком). Но сложность I2C небезосновательна; остальная часть данной статьи поможет вам понять несколько нюансов аппаратной реализации, которые делают I2C настолько универсальным и надежным вариантом для последовательной связи между несколькими независимыми микросхемами.
Видео:Шина I2C.Скачать
Открытый сток
Определяющей особенностью I2C является то, что каждое устройство на шине, должно подключаться к линиям тактового сигнала (сокращенно SCL) и сигнала данных (сокращенно SDA) через выходные драйверы с открытым стоком (или открытым коллектором). Давайте посмотрим, что это на самом деле означает. Сначала рассмотрим типовой CMOS (инвертирующий) выходной каскад:
Если на входе присутствует высокий логический уровень, NMOS транзистор открыт, а PMOS транзистор закрыт. Таким образом, выход имеет низкоомное соединение с землей. Если на входе присутствует низкий логический уровень, ситуация меняется на противоположную, а выход имеет низкоомное соединение с VDD. Это называется двухтактным выходным каскадом, хотя это название не особенно информативно, поскольку оно не подчеркивает низкое сопротивление соединений, которые управляют выходом. В общем случае вы не можете напрямую соединять два двухтактных выхода, поскольку ток будет свободно протекать от VDD до земли, если на одном выходе выдается логическая единица, а на другом – логический ноль.
Читайте также: Ящик с медными шинами
Теперь рассмотрим схему с открытым стоком:
PMOS транзистор был заменен резистором, внешним по отношению к микросхеме. Если на входе присутствует высокий логический уровень, NMOS транзистор обеспечивает низкоомное соединение с землей. Но если на вход подается низкий логический уровень, NMOS транзистор выглядит как разомкнутая цепь, а это означает, что выход подтягивается к VDD через внешний резистор. Такой механизм приводит к двум важным отличиям. Во-первых, появляется неочевидное рассеивание мощности, когда на выходе низкий логический уровень, поскольку ток протекает через резистор, через канал NMOS транзистора на землю (в двухтактной схеме этот ток блокируется высоким сопротивлением закрытого PMOS транзистора). Во-вторых, выходной сигнал ведет себя по-другому, когда на выходе высокий логический уровень, так как выход подключен к VDD через гораздо более высокое сопротивление (обычно не менее 1 кОм). Эта особенность позволяет напрямую соединять два (и более) устройства с открытым стоком: даже если на одном из них низкий логический уровень, а на другом – высокий логический уровень, то подтягивающий резистор гарантирует, что ток не протекает свободно от VDD на землю.
Некоторые последствия использования на шине схемы с открытым стоком:
- Сигналы всегда по умолчанию находятся в состоянии логической единицы. Напримем, если ведущее устройство I2C пытается связаться с ведомым устройством, которое вдруг перестало функционировать, сигнал данных никогда не войдет в неопределенное состояние. Если ведомое устройство не управляет сигналом, то он будет считан как логическая единица. Аналогично, если ведущее устройство выключается в середине передачи, линии SCL и SDA вернутся в состояние логической единицы. Другие устройства могут определить, что шина доступна для новых передач, наблюдая, что и SCL, и SDA находятся в состоянии логической единицы в течении определенного периода времени.
- Любое устройство на шине может безопасно приводить сигналы в состояние логического нуля, даже если другое устройство пытается привести их в состояние логической единицы. Это является основой функции «тактовой синхронизации» или «растяжки тактового сигнала» на шине I2C: ведущее устройство генерирует последовательность тактовых импульсов, но при необходимости ведомое устройство может удерживать линию SCL на низком уровне и тем самым уменьшать тактовую частоту.
- Устройства с различными напряжениями питания могут сосуществовать на одной и той же шине, пока устройства с более низким напряжением не будут повреждены более высоким напряжением. Например, устройство 3,3 В может связываться с устройством 5 В, если SCL и SDA подтянуты до 5 В – схема с открытым стоком приводит к тому, что высокий логический уровень достигает напряжения 5 В, хотя устройство 3,3 В с типовым двухтактным каскадом не может управлять линией 5 В.
Видео:MCP2515, контроллер CAN шины с интерфейсом SPIСкачать
Если у вас есть R, то у вас есть RC
Выходной каскад с открытым стоком ни в коем случае не является стандартной схемой среди цифровых микросхем, и для этого есть причина: он обладает некоторыми существенными недостатками. Один из этих недостатков становится очевидным, когда мы напоминаем, что емкость есть везде. Изменение напряжения ограничено временем, необходимым для заряда или разряда емкости, связанной с определенным узлом. Проблема в том, что подтягивающие резисторы на линиях SCL и SDA ограничивают ток заряда; другими словами, мы имеем гораздо большее сопротивление в RC цепи, постоянная времени которой регулирует переход напряжения от логического низкого уровня в логическому высокому уровню.
Как показывают эти диаграммы, переход от низкого уровня к высокому будет происходить значительно медленнее, чем переход от высокого уровня к низкому, что приводит к классической «пилообразной» форме сигналов I2C:
Читайте также: Дробилка шин в крошку своими руками
Эти две осциллограммы показывают переход от низкого уровня к высокому и от высокого уровня к низкому для тактового сигнала шины I2C с подтягивающим резистором 1 кОм и минимальной емкостью (только два устройства на шине с короткими дорожками на печатной плате).
Видео:подключение к Raspberry pi 5 m.2 nvme ssdСкачать
Как выбрать номинал подтягивающих резисторов
На этом этапе должно быть очевидно, что подтягивающее сопротивление накладывает ограничения на максимальную тактовую частоту конкретной шины I2C. На самом деле здесь оказывают влияние и сопротивление, и емкость, хотя емкость от нас мало зависит, потому что она определяется, главным образом, тем, сколько устройств подключено к шине, и характером соединений между этими устройствами. Это приводит к важному вопросу: «Какой выбрать номинал для подтягивающего резистора?». Компромисс между скоростью и рассеиваемой мощностью: более низкое сопротивление уменьшает постоянную времени RC цепи, но увеличивает величину тока, протекающего от VDD на землю (через подтягивающий резистор), когда на SCL или SDA выставлен низкий логический уровень.
Официальная спецификация I2C (стр. 9) гласит, что напряжение не считается «логическим высоким уровнем», пока не достигнет 70% от VDD. Вы можете вспомнить, что постоянная времени RC цепи говорит нам, сколько времени потребуется, чтобы напряжение достигло примерно 63% от конечного напряжения. Таким образом, для простоты будем считать, что R×C говорит нам, сколько времени потребуется, чтобы уровень сигнала вырос от напряжения, близкого к потенциалу земли, до уровня логической единицы.
Теперь, как найти емкость? «Простой» способ – это сборка всей системы и измерение емкости; по крайней мере, это, вероятно, проще, чем пытаться выполнить точный расчет, который учитывает каждый источник емкости – как отмечает рекомендация от Texas Instruments, «при обычном построении электрических схем формируется невообразимое количество конденсаторов». Если подход с измерением не подходит (как это часто бывает), вы можете выполнить приблизительную оценку, определив емкость вывода для каждого устройства на шине (здесь вам поможет техническое описание), а затем добавить 3 пФ на дюйм дорожки на печатной плате и 30 пФ на фут коаксиального кабеля (эти цифры взяты из той же рекомендации, стр. 3).
Предположим, что у нас емкость шины составляет 50 пФ, и мы хотим соответствовать спецификации «стандартного режима» I2C, в которой указано, что максимальное время нарастания составляет 1000 нс.
\[t_ =1000\ нс=\left(R\right)\left(50\ пФ\right)\ \ \Rightarrow\ \ R=20\ кОм\]
Таким образом, можно соответствовать требованиям спецификации с Rподтягивающий = 20 кОм : это значение также дает минимальное энергопотребление. Как насчет скорости? Предположим, вы хотите, чтобы длительность присутствия высокого логического уровня на линии синхронизации было, по крайней мере, в три раза больше времени нарастания.
Если 167 кГц не достаточно много, вы можете снизить сопротивление (за счет увеличения энергопотребления), пока не достигните желаемой тактовой частоты. (Фактически, «стандартный режим» ограничивает тактовую частоту до 100 кГц, но вы можете адаптировать эти спецификации под потребности вашей системы.)
Это грубые расчеты, но, честно говоря, вам не нужно беспокоиться о том, чтобы найти идеальное сопротивление. Этот общий подход может помочь вам поставить резистор разумного номинала, и вы всегда можете поменять резисторы, если что-то работает не так, как вы хотите.
Видео:Введение в шину I2CСкачать
Заключение
Если эта статья выполняет свою цель, то вы теперь хорошо знакомы с основными деталями, связанными с разработкой аппаратного обеспечения I2C. А реализацию программного обеспечения мы рассмотрим в отдельной статье.
🎬 Видео
Установщик адресов Flash-i2cСкачать
I2C интерфейсСкачать
Передача данных - шина SPIСкачать
Устранение помехи от шины I2C в одноплатной версии SDR трансивераСкачать
P82B715 - Удлинитель шины I2C, на 20 метров по витой паре.Скачать
Логический LIN пробник, цифровой тестер лин, к лайн шины автомобиля. На Ардуино, OLED I2C, TJA 1020Скачать
Шина данных i2c - декодируем/синхронизируем с помощью осциллографа Lecroy!Скачать
25 Шина I2CСкачать
лекция 403 CAN шина- введениеСкачать
I2C мультиплексор TCA9548A или как подключить несколько часов к Arduino?Скачать
Шина I2CСкачать
Декодер протоколов | Часть первая I2C снифферСкачать
Что такое I2C ??? Подключаем GY-521 и Oled 96*16 к STM 32Скачать