Вы находитесь на странице: 1из 31

1/1.

Детальный "въезд" в последовательный интерфейс I2C


(с "песнями, плясками и влезанием в шкуру его разработчика").

В идеале, "раскрутка" любой, хотя бы, более-менее сложной темы, должна начинаться с ответа
на законный вопрос: "Зачем все это нужно, и что я с этого буду иметь"?
В части касающейся заявленной темы, частично, ответ на этот вопрос был дан в 23-м
разделе "Самоучителя...".
Напоминаю смысл сделанных в нем выводов.
1. Последовательный интерфейс, по сравнению с параллельным, является менее
быстрым, но позволяет получить существенный выигрыш, выражающийся в
уменьшении количества выводов порта/портов, задействовованных для организации
обмена данными между "мастером" и "помощником".
Это позволяет создавать устройства с расширенными функциональными
возможностями (освободившиеся выводы порта/портов можно задействовать под
решение дополнительных задач) и приводит к удешевлению устройства (можно
обойтись меньшим, чем в случае использования параллельного интерфейса,
количеством портов, а это есть выигрыш по деньгам).
2. В части касающейся м/контроллеров (и ПИКов в частности), последовательный
интерфейс I2C более выгоден, чем последовательный интерфейс RS232 по причине
того, что интерфейс I2C расчитан на работу со словами объемом 8 бит (а не со словами
объемом 11 бит, как в случае применения RS232).
В этом смысле, "полной любви и согласия" между "мастером" и "помощником" можно
достигнуть "малой кровью".
3. Интерфейс I2C является двунаправленным и с возможностью изменения скорости
обмена данными между "мастером" и "помощником", по ходу исполнения программы
"мастера", в широком диапазоне скоростей (от максимальной и до близкой к нулю).
Если речь идет о фиксированной (неизменной) скорости обмена, то, в пределах этого
диапазона, можно выбрать любое ее значение.
4. Интерфейс I2C является надежным, так как "помощник", при помощи бита
подтверждения (АСК), сообщает "мастеру" об успешности (или нет) обработки текущего
байта (с любой, "вложенной" в него, функциональностью).
При наличии ошибки, "мастер" ее может исправить (реализуется программно), то есть,
переписать или произвести повторное считывание "бракованного" байта (или группы
байтов, в состав которой он входит).
Итак, грубые "мазки" на "портрет" интерфейса I2C "наляпали" ("обозначили контуры").
Если сейчас что-то не понятно, то это беда небольшая: ниже будет поэтапная "зачистка"
("расстрел" понятийных проблем).
Развиваю тему.
ПИК ("мастер"), по определению, работает со словами, объем которых равен байту.
Для достижения "взаимной любви и согласия" (без "скандалов" и "битья посуды"),
"помощник" также должен работать со словами, объем которых равен байту.
"Яйцеголовые" понапридумали достаточно большое количество "помощников",
работающих по интерфейсу I2C ("если есть поп, то будет и приход") и под различные
нужды.
Таким образом, наряду с многофункциональным "мастером" ("важняк"), возможностей у
которого "выше крыши" (он "и сеятель, и жнец, и на дуде игрец"), нужно разобраться и с
"мелкотравчатым (калибр не тот) помощником", иначе "мастеру" не будет понятно, как
"рулить помощником" или как "отвесить ему оплеуху", если он "от работы увиливает"
(делает ошибки).
Короче, все как в жизни: есть руководитель с высоким статусом, который "рулит"

1
подчиненным с более низким статусом.
"Помощник" является "мелкотравчатым" в том смысле, что с "мозгами" у него туговато:
что на заводе-изготовителе в него заложили, тем и пользуется. Никакой инициативы и
полета мысли.
Короче, что-то близкое к "дебилу", который все делает только "из под палки" (которым
нужно конкретно и жестко руководить).
"Мастер", в этом смысле, поинтеллектуальнее будет, так как в него заложена программа,
составленная программистом, то есть, живым человеком (с мозгами и прочими
атрибутами).
По большому счету, и "мастер" тоже дебил (особенно изначально, на стадии
"болванки"), но ему кое-что перепадает от интеллектуальных щедрот программиста
(программа), и именно за счет этого он имеет высокий статус начальника с хорошей
зарплатой.
Всем же этим "спектаклем", из-за занавеса, "рулит" (через "мастера") программист.
Он имеет суперстатус "серого кардинала".
Роли в этом "спектакле" распределяются так: программист "рулит мастером" (через
программу, заложенную в него), а "мастер рулит помощником".
То, что Вы прочитали, есть элементарная расстановка приоритетов.
Зачем она нужна?
Затем, чтобы выработать четкий и, самое главное, успешный, план "боевых действий".
Вопрос: "Каков 1-й пункт этого плана"?
Ответ: вспомните, например, про закон Ома: ток "стремится" течь по пути наименьшего
сопротивления, что в переводе на русский означает: "разборки" нужно начинать с того,
что попроще.
Кто в нашем "спектакле" имеет самый низкий статус и самый "мелкотравчатый"?
"Помощник".
Вот его первым и "пытать" будем.
На данный момент, "помощник" прорисован в общем виде и очень не конкретно ("ежик
в тумане"). С этим нужно что-то делать, так как совершенно не понятно, кого "пытать" и
"откуда у него вообще ноги растут".
Да к тому же, этих самых "помощников" еще и целая "рота"...
Оптом, "пытать" всю "роту" - себе дороже станет (в этом случае, "вектор пытки"
разворачивается на 180 градусов). Этот вариант совсем не подходит.
Опять упираюсь в необходимость расстановки приоритетов, с целью "сужения сектора
обстрела".
Каков критерий этой расстановки?
А самый жизненный - степень "ширпотребности" и практической востребованности
того или иного "помощника".
В этой "иерархии", безусловным лидером является "помощник", реализующий функцию
внешней (относительно "мастера"), энергонезависимой памяти.
Собственно говоря, "шкурная" необходимость в реализации именно этой разновидности
"помощника", работающего с байтами по последовательному интерфейсу, и заставила
"яйцеголовых" поднапрячься, в результате чего и "родился" интерфейс I2C.
Вопрос: "Каков мотив этой "шкурной" необходимости"?
Ответ: малый объем EEPROM памяти данных микроконтроллеров (не зависимо от их
типа).
Что значит 64 или 128 ячеек EEPROM памяти данных?
Капля в море потребностей.
А если в EEPROM память данных нужно "загнать", например, 1, 2, 8 и т.д. килобайта
данных (информации), да еще и сохранить их после выключения питания, с целью

2
дальнейшего их использования в каких-то нужных целях (при последующих
включениях питания)?
В этом случае, без внешней (по отношению к ПИКу), дополнительной EEPROM памяти
данных, никак не обойтись.
То, что Вы прочитали, и есть "шкурная" суть весьма обширного класса практических
задач, решения которых "упираются" в необходимость организации внешней EEPROM
памяти данных большого (относительно объема EEPROM памяти данных
м/контроллера) объема.
А какие возможности открываются! Дух захватывает.
Это стоит того, чтобы поднапрячься при "въезде".
Основную "массу" этого "счастья" назвали многократно перепрограммируемыми
микросхемами энергонезависимой памяти последовательного типа .
Естественно, в первую очередь, для работы в "связке" с м/контроллерами (а иначе, за что
кровь проливали?), их "общение с внешним миром" организовали по интерфейсу I2C.
Сразу оговорюсь: есть и другие типы последовательных интерфейсов, работающих со
словом объемом в 8 бит или словом объемом кратным 8 битам, но конкуренции с I2C
они не выдерживают (хотя и применяются, но не так массово).
Короче, интерфейс I2C считается мировым стандартом и большая часть "помощников"
последовательного типа работает именно по нему.
Итак, "пытать" будем м/схему EEPROM памяти данных последовательного типа,
работающую по интерфейсу I2C.
... опять их целый "взвод".
Но уже легче, так как, во-первых, "взвод" это не "рота", а во-вторых, практически все
"бойцы" на одно лицо (единообразные, с тупыми физиономиями и
непринципиальными различиями).
Так что, смело можно "выводить из строя" любого.
Отработав на нем наиболее эффективные приемы "приведения в чувство", их можно
будет, с комфортом, применить и к остальным.
Ага, вот этот, улыбающийся, подойдет (что-то он разулыбался?).
"Кто таков? Звание, имя"?
"Микросхема 24С64А фирмы "ATMEL", 8 килобайт пустой памяти. Рад стараться"!
"Это что же получается? Родом из буржуев, да еще и с амнезией"?
"Так точно, из буржуев я. Мозгов до фига, но память отшибло. Ничего не соображаю и
делать ничего не умею"!
"Да ... Тяжелый случай".
"Ну ничего, боец. Крепись. Я тебя через "бормашину" и "выкручивание конечностей"
вылечу. Вспомнишь даже то, чего никогда и не знал. А после этого, я к тебе, чтобы не
баловался, своего сержанта приставлю".
Что такое 24С64А и "за что его дергать"?
Вот это уже совсем другое дело: есть вполне конкретный предмет разговора, то есть, можно
"долбить в одну точку" до победного конца, чем я сейчас и займусь.
Формулирую смысл этой "долбежки": программист должен четко знать алгоритм работы
"помощника" для того, чтобы грамотно и безошибочно составить программу для
"посредника" (между программистом и "помощником"), роль которого исполняет
"мастер" (ПИК).
Знакомимся с м/схемой 24С64А:

3
Вы видите самый "ходовой" ее вариант - в корпусе PSDIP8.
Главное преимущество последовательного интерфейса перед параллельным сразу же
бросается в глаза - малое количество выводов, и как следствие этого, малые размеры
корпуса.
Функции выводов
Про GND и Vcc (+5в) говорить не буду, все и так понятно.
Что такое А0, A1 и А2?
Это подарок "яйцеголовых". Они подсуетились так, что к одной шине I2C можно
подключить сразу несколько "помощников", с условием того, что они будут работать
по-отдельности (в противном случае, будет электрический конфликт в виде
объединения низкоомных выходов).
Зачем это нужно?
А для наращивания объема памяти: считали информацию из одной м/схемы,
отключили ее от шины I2C (при этом, выходы переводится в высокоомное состояние),
подключили к ней другую м/схему и считывайте дальше на здоровье.
То же самое относится и к процедуре записи.
В особо "изощренных" (комбинированных) случаях, можно и считывать информацию из
какой угодно м/схемы, и записывать ее в какую угодно м/схему (естественно, из числа
подключенных к шине I2C). Нет проблем, но только с обязательным соблюдением
условия: в любой момент времени, к шине I2C не должно быть подключено более
одной м/схемы.
Отсюда становятся понятными и функции выводов А0, A1 и А2: это адресные входы,
предназначенные для "рулежки" микросхемами памяти (корпусами, кристаллами -
можно назвать как угодно).
В зависимости от распайки этих выводов (каждый из них может быть соединен либо с
корпусом, либо с плюсом источника питания), "мастер" формирует соответствующий
код (он совпадает с этой распайкой), и будь здоров: именно та м/схема памяти, у
которой распайка совпадает с этим кодом, и подключится к шине I2C (будет активной),
а остальные м/схемы памяти (с другими распайками) будут от шины отключены (не
активны).
В данном случае (24С64А), имеется три адресных линии (у других типов м/схем памяти
их может быть меньше), что позволяет подключить к шине I2C до двух в третьей
степени (8-ми) м/схем.
Вот и считайте: в случае применения 24С64А, это 8х8=64 килобайта (512 килобит)
памяти. Очень внушительно.
Если нужно вообще отключить от шины I2C все м/схемы памяти, то просто
формируется адрес, обращающийся в никуда (на деревню, дедушке).
Под это дело нужно задействовать один из 8-ми кодов. Соответственно, в этом случае,
максимальное количество м/схем, которое можно будет подключить к шине I2C,
сократится до 7-ми.

4
Не нужна "рулежка" таким большим количеством м/схем?
Да ради Бога, можно как угодно уменьшить их количество, только при этом нужно не
выпускать из поля зрения адресные коды, так как часть из них станет не активными
(запрос на деревню, дедушке).
Какой-то особой премудрости в этом нет.
К шине подключена только одна м/схема?
В этом случае, вообще "персик":
- не нужно задействовать выводы порта "мастера" под формирование адресных кодов (и
соответственно, формировать их программно),
- в простейшем случае, выводы А0, A1 и А2 соединяются с корпусом.
Так как далее я планирую работу только с одной м/схемой памяти, то прошу учесть этот
чисто практический вывод.
Каковы функции вывода WP?
Если на него подать 1, то не возможно будет записать байты в ячейки, находящиеся в
верхней половине памяти (по старшим адресам).
Этот "сектор" выделяется для первоначальной записи каких-то важных данных (WP=0),
менять которые в дальнейшем не нужно.
Затем, на выводе WP, "на веки вечные", устанавливается единица (он распаивается на
+5в) и "дело в шляпе": считать из этого "сектора" первоначально записанные в него
данные можно, а записать в него что-то новенькое - нельзя.
Обычно, в верхнюю половину памяти, первоначально (например, на заводе-
изготовителе, озабоченном целостностью каких-то важных байтов), записывают какие-
то "эталоны", "опознавательные знаки" или другой "важняк", а потом - "концы в воду"
(WP=1).
По большому счету, это бесполезный "прибамбас" (расчитан на "лохов"), так как ничто
не мешает убрать с вывода WP единицу и посадить на него ноль.
Он нам сейчас нужен, как корове пятая нога, а посему, "цепляем" вывод WP на корпус
"на веки вечные" (разрешаем запись по всему объему памяти).
Что получилось?
А получилась "красота": 5 выводов из 8-ми - на корпусе. Один вывод - плюс источника
питания (5 вольт).
Остались 2 самых главных вывода: SCL и SDA.
Вот это уже настоящий "важняк", требующий глубокого уважения.
Почему на рис. 1 я пометил соответствующие этим выводам надписи красным цветом?
Потому, что оба этих вывода, в комплексе, и есть составная часть того, что я называю
"шиной I2C".
С целью формирования четких "правил игры", определяюсь с терминологией.
Шина I2C и интерфейс I2C это не одно и то же (их часто путают и получается черт
знает что).
Интерфейс I2C это "глобальное" понятие, включающее в себя весь комплекс
аппаратных и программных средств, необходимых для его реализации.
Проще говоря, Вы не ошибетесь, если отнесете к интерфейсу I2C любую "детальку",
которая имеет к нему прямое отношение.
Шина I2C это физическая (аппаратная) часть интерфейса I2C, которую можно увидеть
глазами и пощупать руками.
То есть, это два вывода (SCL и SDA) со стороны "мастера", два вывода (SCL и SDA) со
стороны "помощника" и две "проволочины" (линии), которые все это "хозяйство"
соединяют между собой.
Естественно, при этом, должны быть обеспечены следующие физические соединения:
- вывода SCL "мастера" с выводом SCL "помощника",

5
- вывода SDA "мастера" с выводом SDA "помощника".
По-моему, это наиболее удобное и конкретное "разграничение полномочий", "ставящее
крест" на терминологической путанице, которой сопровождаются "операции" с этими
понятиями.
Теперь нужно определиться с тем, каким именно должно быть объяснение достаточно
занудной (особенно на первых порах) информации, чтобы "мозги прошибло"?
"Почесав свою репу", я пришел к выводу, что нужно поставить себя на место
разработчика этого "чуда" (I2C), то есть, сыграть некий "моноспектакль", состоящий из
одного, большого и задумчивого монолога.
По-моему, это самый эффективный и "пробивной" путь объяснения.
Так что, устраивайтесь поудобнее и все внимание на "сцену".
Вживаюсь в образ (обращаю внимание - опять речь идет о таком важном понятии, как
образ) и перевоплощаюсь.
Итак, я есть разработчик, и передо мной стоит задача "сварганить" последовательный
интерфейс, работающий с байтами.
Совершенно понятно, что нужна линия, по которой "циркулировали" бы данные.
Назначаю ее (линия данных) и "обзываю" вывод, который подключается к этой линии,
SDA (а можно назвать и ЁКЛМН).
Теперь "вскакивает" вопрос о такте: побитно, байт ведь не может читаться/записываться
бесконечно? Каждый его бит должен обрабатываться в течение некоторого времени, что
и есть суть такта.
Если организовать в "помощнике" свой, внутренний такт, то "вскочит" вопрос о
синхронизации двух функционально обособленных тактов "мастера" и "помощника",
что моментально "убивает сладкие грезы" о возможности эффективной и
широкодиапазонной регулировки скорости обмена данными (в том числе и по ходу
исполнения программы "мастера"), ведь синхронизация это достаточно инерционный
("тормозной") процесс, и с уменьшением скорости обмена данными, эта инерционность
начинает выходить "за грань разумного".
Плюс еще куча всяких бяк, "биться" с которыми себе дороже станет, да и скучно это
(пройденный, "неандертальский" этап).
Единственный практический вывод из этих, пока бесплодных, рассуждений: хочешь -
не хочешь, но, в любом случае, под "тактовые дела", выделить одну линию шины
придется (то ли под сам такт, то ли под сигнал синхронизации, то ли под еще какую-то
"тактовую страсть").
Назначаю ее (линия такта) и "обзываю" вывод, который подключается к этой линии,
SCL.
Теперь "шевелю извилиной" с целью ответа на вопрос: может ли "помощник" работать
без своего внутреннего такта?
Ответ: совсем без такта ну никак нельзя, иначе "вся жизнь замрет", так как это есть
"убийство помощника" (и вообще, любого цифрового устройства) "в чистом виде".
Внутренний такт тоже не нужен (см. выше).
Остается внешний такт. Это уже ближе к делу.
Источник внешнего (по отношению к "помощнику") такта напрашивается сам по себе -
"мастер" (выбирать особо не из чего).
Если "мастер" будет формировать на линии такта (SCL) внешний (для "помощника")
такт и обеспечит фазовую "привязку" этого такта к "циркулирующим" по линии данных
(SDA) байтам, то задача будет решена.
И в самом деле, при таком "раскладе", синхронизация работы "мастера" и "помощника"
обеспечивается автоматически, без принятия каких-то "крутых" мер по формированию
"фазовых пинков" (той или иной силы), являющихся главными атрибутами

6
синхронизации двух функционально обособленных тактов.
"Мастеру" синхронизировать самого себя не нужно (глупое занятие), а "помощник
своего мнения не имеет" и подобострастно "смотрит в рот своему начальнику" (тактовая
"строптивость" на полном нуле. Короче, раб).
Собственно говоря, в этом случае, по факту, о синхронизации тактов и речи не идет, так
как "эталон" в наличии имеется (такт ПИКа), а такта, который бы подстраивался под
этот "эталон", нет.
Красота! Синхронизировать нечего: такта не два, а один, а синхронизировать самого
себя - идиотское занятие.
А раз такт один, то он "и Бог и царь и воинский начальник": захочу, "выстрелю" байт за
доли секунды, а захочу, буду выдавать его целый день.
Ай да я (в смысле, не лично я, а разработчик "за бугром"), ай да сукин сын!
На "золотую жилу" нарвался (Клондайк и Эльдорадо вместе взятые)!
В подобных случаях, самое главное - "не наложить от радости в штаны", а взять все то,
что только можно (по максимуму), причем, по праву сильного.
Примечание: в некоторых описаниях работы интерфейса I2C утверждается, что он
асинхронный.
В моем понимании, понятие "асинхронный" "привязано" к случайным (относительно
такта) событиям (я об этом писал в статье об асинхронном стимуле), а в данном случае,
о них речи не идет, так как все, что "творится" на шине I2C, четко "привязано" к такту.
Лично я, в части касающейся синхронизации, классифицирую шину I2C на свой лад,
как "автоматически синхронную шину".
Может быть, такое определение и не вполне корректно, но, лично мне, так просто
удобнее "переваривать" информацию.
Кто-то может думать по-другому, лишь бы от этих дум был практический толк.
Поехали дальше.
Опять расставляю приоритеты.
Вопрос по-русски, то есть, прямо в лоб: "Для чего затеяна вся эта свистопляска"?
Ответ: для того, чтобы записать в ячейку памяти байт (байты) данных и считать из
ячейки памяти байт (байты) данных.
После такого ответа, не нужно быть семи пядей во лбу, чтобы понять, что "взлом"
интерфейса I2C нужно начинать с выяснения алгоритмов передачи (приема) байта
данных, а не с выяснения того, что сопутствует этому "важняку" ("технологические"
байты адресации, выбора режимов и старт-стопные условия).
Раз сопутствует, значит прилагается, то есть, речь идет о вторичном, а вторичное может
и подождать.
В абсолютно всей прочитанной мной информации по интерфейсу I2C других авторов,
этот порядок "въезда" поставлен "с ног на голову" в том смысле, что "заходы"
осуществляются "с другого конца".
Результат: нарушение рационального порядка "въезда", сопровождающееся
"вываливанием на бедную головушку" далеко не полной и не всегда качественной
информации, при "разборках" с которой, "не тренированная извилина завязывается на
три узла".
Такого "счастья" я Вам не желаю, а посему, объясню информацию так, как она, по
здравому разумению, и должна объясняться, а именно: изначально, "падаю" на байт
данных ("важняк"), а после его "взлома", на все то, что его "обслуживает", в порядке:
байты адресации, "режимный" байт, старт-стопные условия.
После этого, "собираю все это хозяйство до кучи".
Казалось бы, мудрость не велика, однако ...
Итак, "томагавки наголо".

7
С целью дальнейшего "сужения сектора обстрела", на данном этапе, нужно четко
определиться, к какой из двух процедур (чтение/запись) "привязаться".
С моей точки зрения, изначально, выгоднее "привязаться" к процедуре записи
"мастером" байта данных в ячейку памяти "помощника", как к наиболее привычной
(вспомните про частотомеры на ЖКИ) и удобной для понимания.
Исходя из сказанного выше, предполагаю, что ячейка памяти "помощника" уже заранее
выбрана, и режим записи в нее байта данных выставлен.
Вывод "мастером" байта данных на шину I2C.
Рассуждаю.
Если "мастер" производит запись байта данных в ячейку памяти "помощника" (данные -
на линии SDA), то он же ("мастер") должен сформировать, под этот байт данных,
импульсную последовательность такта на линии SCL.
И это естественно, так как байт данных состоит из 8 битов, и для того чтобы "помощник
знал", что именно, побитно, нужно записывать в свою ячейку памяти (0 или 1),
состояния всех битов байта данных нужно, для начала, как бы "просканировать" (а
проще говоря, узнать и записать в оперативную память).
Следовательно, моменты этого "сканирования" должны быть "привязаны" к каким-то
стробам.
Напоминаю, что стробом называется активный перепад уровней (от 0 к 1 или от 1 к 0),
запускающий какой-то процесс (вспомните про нажатие на курок).
А такт сгодится? Еще как сгодится: он под это дело и придуман.
Что, в данном случае, есть такт?
В общем виде, это последовательность импульсов, формируемая "мастером".
А раз это так, то и перепады в ней имеются, причем, обеих видов.
Нужно только назначить активным какой-либо из них (от 0 к 1 или от 1 к 0).
Не объясняя причин (это выяснится позднее), скажу, что стробом назначен переход от 0
к 1 (фронт).
На данном этапе, углубляться в причины этого конкретного назначения я не вижу
практического смысла, так как можно "уйти в сторону от генеральной линии", что есть
распыление внимания.
К тому же, порядок смены уровней активного перепада, по ходу разработки, всегда
можно переназначить (если в этом есть необходимость).
Далее следует незамысловатый вывод, "привязанный" к конкретному порядку смены
уровней активного перепада: с точки зрения надежности работы устройства, переход от
0 к 1 на линии SCL (текущий строб) должен произойти тогда, когда на линии SDA
гарантированно надежно установится уровень текущего бита данных (0 или 1).
Объясняю "привязки": в байте 8 битов. Под каждый из этих битов, должен быть
сформирован "свой" строб.
Следовательно, тактовая последовательность, выдаваемая "мастером" под один байт
данных, должна состоять из 8 импульсов (16 перепадов, половина из которых не
активна).
Первый строб должен запускать процесс записи в выбранную ячейку памяти уровня
первого бита данных, второй строб - второго бита данных, третий - третьего и т.д. (до 8-
го бита данных включительно).
Сразу оговариваюсь: эта нумерация условна. Она отражает только последовательность
расположения битов в байте, но не отражает порядка их старшинства (об этом - ниже).
Еще один важный вывод: так как стробирование должно происходить после
гарантированно надежной установки уровней битов на линии данных, то начало
формирования байта данных на линии SDA должно опережать, по фазе (по времени),
начало формирования тактовой последовательности импульсов на линии SCL, которая

8
вырабатывается "мастером" под этот байт данных.
Проще говоря, сначала "мастер" должен выдать в линию SDA бит данных, а только
после этого (с небольшой задержкой) выдать в линию SCL строб под этот бит.
Для "мастера", обеспечить фазовый сдвиг (задержать одну импульсную
последовательность относительно другой) - плевое дело и ничего особо сложного в
этом нет (подробно "расписано" в "Самоучителе...").
Это есть "глобальное" правило, которое должно строго учитываться при любом
"скоростном режиме" (в пределах дозволенного) обмена данными между "мастером" и
"помощником".
Какова должна быть величина этого опережения?
Это уже вторично и не стоит пока распылять внимание на мелкие детали, не выяснив до
конца "глобальное" (всему свое время).
Следующий "глобальный" вопрос: каков порядок обработки битов байта данных?
Ответ: выгодно "привязаться" к стандарту.
В соответствии с ним, обработку битов байта лучше начать с бита самого старшего
разряда и далее, в порядке убывания старшинства разрядов.
Итак, то, что я, на данный момент, "нарыл", можно отобразить при помощи этих эпюр:

Сразу обращаю Ваше внимание на то, что я специально обрезал все то, что находится за
пределами интервала времени прохождения байта данных, так как туда я еще свой нос
не совал (но скоро суну).
Глядя на эту "живопись", меня начали "терзать смутные подозрения": где-то я это видел?
Вызываю летающую корову по имени HT1611/1613 и устраиваю ревизию ее мешка с
нулями и единицами.
Выясняется, что точно такой же принцип формирования стробов (строб формируется
под каждый бит байта) применяется и в работе с м/контроллерами HT1611/1613
(оказывается, что "мы не одиноки во вселенной"!).
Это практически подтверждает вывод: строб обязательно должен быть, и он должен
быть сформирован на "спокойном участке", то есть, после гарантированного
окончания переходных процессов, сопровождающих смену/смены уровней на
линии данных.
Если сформировать строб во время переходного процесса, то результат идентификации
значения бита (байта) будет непредсказуем, что означает "Караул! Убивают!".
Спасибо, коровка. Справно службу тащишь. Подкормись на сочном лужку и в добрый
путь.
Остаюсь один на один "с голым задом проблемы", но он уже не такой грозный, как

9
раньше (осунулся).
Для "полного счастья" в вопросе о стробах, осталось только выяснить: какова, в общем
виде, должна быть величина задержки начала "пачки" импульсов такта относительно
начала "пачки" импульсов байта данных? Может быть есть какая-то специфика (по
отношению к HT1611/1613)?
На рис. 2, эта задержка обозначена как Тз.
"Слабоват" будет рисунок 2 в том смысле, что он не учитывает реалий жизни: в этом
бренном мире, ничего за ноль секунд не делается.
Переходные процессы, которые сопровождают смены уровней, требуют, для своего
завершения, пусть и малого, но времени (инерционный процесс), а посему, нужно
адаптировать рисунок 2 к реалиям.
"Живопись" получилась вот такая:

Если объяснить по-простому, то, на уровне эпюр, под "реалиями жизни" подразумевается
"переход от прямоугольного к косому".
Это "косое" (наклонное) и отражает (в общем виде) "глубинную суть" переходных
процессов, которые сопровождают смены уровней, причем, в цифровой технике (а не
только в рассматриваемом случае), переходные процессы есть "глобальный" атрибут не
только смены уровней, но и других более "навороченных" (комплексных) процессов.
Уровни меняются не мгновенно (не за нулевое время), и для их смены требуется какое-
то время (это Вы и видите на рис. 3).
Если рассуждать "галлактически", то речь идет об инерционности, которая присуща
всему, что нас окружает (исключений нет).
Какое для этого нужно время?
В разных случаях, по-разному.
В первую очередь это время определяется верхней границей быстродействия
аппаратной части "наиболее слабого звена в цепи империализма" ("мастера" или
"помощника": это нужно выяснять конкретно, для каждого случая).
Что означают, казалось бы, юмористические надписи "Разброд и шатания (для такта или
данных)"?
А то и означают - самые натуральные разброд и шатания.
В переводе на математический язык, это означает то, что в секторах с этими
несерьезными названиями, вероятности идентификации нуля или единицы примерно
равны. Вот вам и разброд с шатаниями (бардак, хаос, черт знает что и т.д., короче,
никакой определенности).
В переводе на язык конструктора (с астрономическим уклоном), это означает то, что, в
период прохождения (во времени) этих "черных дыр", лучше "сложить лапки" и не
предпринимать никаких активных действий, иначе "удар в челюсть" гарантирован на

10
все двести процентов.
Каков выход?
Да он простой как амеба: просто переждать эту "напасть" (а ничего другого не остается)
и "раньше времени не дергаться".
Бороться с ней бесполезно. Это все-равно, что, например, пытаться изменить закон Ома
(закон природы).
Никакой трагедии из этого делать не нужно по причине того, что переходные
процессы, сопровождающие смены уровней, очень быстротечны (но на эпюре, я их, для
наглядности, непропорционально растянул вширь).
У современных цифровых м/схем, длительность подобного рода переходных процессов
(на эпюрах - наклонные участки) составляет порядка десятков наносекунд, а у
быстродействующих м/схем и того меньше.
Предварительный, практический вывод из сказанного выше: идентифицированы
"черные дыры" (а это есть великое дело). В них лучше не лезть (в этом случае,
"катаклизм" обеспечен), а просто переждать эту "беду".
Исходя из этой "концепции", и с учетом сформулированной выше "сдвиговой"
проблемы, временной сектор "разброда и шатания для такта" должен находиться правее
временного сектора "разброда и шатания для данных", причем, для перестраховки
(береженого Бог бережет), между этими секторами должен быть "ефрейторский,
временной зазор" (накладки, во времени, одного сектора на другой, допускать нельзя).
Временной "зазор" также должен быть и между правой границей сектора "разброда и
шатания для такта" и левой границей сектора "разброда и шатания для данных"
следующего (во времени) бита данных.
Для наглядности, я все это хозяйство поместил в бит данных №6 и раскрасил его как
"индейца на тропе войны".
То же самое можно было бы сделать и с остальными битами, но я не стал "палку
перегибать" (чтобы "в глазах не рябило").
Красным цветом показан сектор "разброда и шатания для такта", перенесенный в
нижнюю эпюру из верхней.
Зеленым цветом показаны "ефрейторские зазоры" справа и слева от красного сектора.
"Мораль сей басни такова": для обеспечения высокой надежности функционирования
шины I2C, красный сектор должен располагаться внутри зеленого сектора.
При этом, положение красного сектора, внутри зеленого сектора, может быть любым,
при условии, что красный сектор не "выезжает" за границы зеленого сектора.
Для перестраховки (по надежности работы), и справа, и слева от красного сектора,
должны быть "ефрейторские (зеленые) зазоры".
Рассуждаем дальше.
Обе последовательности импульсов формирует "мастер", следовательно, при условии
обеспечения им первичности (во времени) формирования бита данных и вторичности
формирования строба под него, любая фиксированная задержка импульсной
последовательности такта (всех его импульсов), сдвинет (во времени или по фазе) все 8
красных секторов (стробов) внутри соответствующих 8-ми зеленых секторов, причем,
на одинаковый интервал времени.
Величина этого сдвига будет определяться длительностью задержки (чем больше
задержка, тем больше сдвиг красного сектора вправо).
Ну и прекрасно!
"Сваяли" в программе тактовую задержку требуемой величины для одной "связки" типа
"бит данных - строб под него", и для всех остальных импульсов "пачки" импульсной
последовательности такта, будет обеспечен точно такой же фазовый сдвиг (вправо
сдвинется вся "пачка").

11
Это возможно при условии многоцикличности подпрограммы обработки битов байта, в
полный цикл которой "врезана" (ниже группы команд формирования значения бита
данных. Бит данных формируется первым) группа команд формирования импульса
такта.
Все это уже мы проходили при "разборках" с ЖКИ на основе HT1611/1613 (см.
"Самоучитель..."), и ничего суперсложного, в таком принципе формирования фазового
сдвига одной последовательности импульсов относительно другой, нет.
Таким образом, для того чтобы обеспечить безошибочную запись байта данных по шине
I2C (напоминаю, что речь идет пока только о формальной записи байта данных, без
учета того, что ее сопровождает), исходя из сказанного, необходимо выполнить
следующую последовательность действий:
1. Сначала, "мастер" должен начать формирование текущего бита данных.
2. Через некоторое время после начала формирования текущего бита данных (он еще не
сформирован и продолжает формироваться), "мастер" должен сформировать активный
перепад (строб) на линии такта с таким расчетом, чтобы он располагался в некотором
отдалении от зоны "разброда и шатания для данных" (справа от него) текущего бита
данных, что и есть фазовый сдвиг (задержка).
Этим обеспечивается идентификация (или "запуск в работу") текущего бита данных,
уровень которого гарантированно надежно установился после полного окончания
переходных процессов, сопровождающих смену уровней на линии данных.
Уровни на линии данных не всегда могут меняться (это зависит от числового значения
байта), например, при записи числа .255 (1111 1111) и т.д., но "выпендриваться" по
этому поводу (изменять величину задержки) не стоит (себе дороже станет), а лучше
сработать так же, как и в случаях смены уровней, то есть, все стробы должны быть
задержаны на одно и то же время (вне зависимости от числового значения
записываемого байта).
3. "Мастер" завершает формирование текущего бита данных и сразу же начинает
формировать следующий бит данных, который, после этого, становится текущим.
При этом, должен быть обеспечен правый "ефрейторский зазор" (см. рис. 3: зеленый
сектор справа от красного), необходимый для формирования пассивного (не активного)
тактового перепада.
Это нужно для того чтобы, в дальнейшем, можно было бы сформировать следующий
активный перепад (строб).
Даже на высоких скоростях записи, приемлемая величина этого "ефрейторского зазора"
(правый, зеленый сектор) обеспечивается за счет того, что формирование пассивного
тактового перепада требует определенного времени, что, "в переводе на русский",
означает: если с формированием пассивного перепада проблем нет, то не будет проблем
и с правым "ефрейторским зазором".
Если же скорость записи существенно ниже предельно возможной (а это имеет место
быть в большинстве случаев), то про правый "ефрейторский зазор" можно вообще
забыть.
То же самое относится и к чтению.
Теперь обратите внимание на надпись "Смена уровней на линии данных".
Смена уровней на линии данных, принципиально, ничем не отличается от смены
уровней на линии такта.
То есть, она также должна производиться на "спокойном участке", но только верхней
эпюры.
С учетом сказанного, можно сделать вывод: для обеспечения надежной работы по
интерфейсу I2C, смена уровней на линии данных должна происходить только
тогда, когда преходные процессы, сопровождающие смены уровней на линии

12
такта, полностью закончились.
Это Вы и видите.
В данном случае, смена уровней на линии данных должна происходить при
надежно зафиксировавшемся нулевом уровне на линии такта.
Чем это обеспечивается?
Да все той же задержкой "пачки" импульсов такта по отношению к "пачке" импульсов
байта данных, так как происходит задержка, во времени, всех перепадов (и активных, и
не активных) импульсной последовательности такта.
В итоге, этот фазовый сдвиг решает двуединую задачу, и в этом смысле, он является
универсальным, то есть, одной и той же задержкой (Тз) обеспечиваются:
1. "Прохождение" строба в момент гарантированно надежной установки уровня
бита данных (под который этот строб формируется) на линии SDA.
2. Смена уровней на линии данных (SDA) в момент гарантированно надежной
установки нуля на линии такта (SCL).
Эти 2 пункта нужно очень хорошо запомнить и уяснить ("важняк").
Рисунок 3 я "сваял" с целью концентрации внимания на переходных процессах,
сопровождающих смены уровней.
Такого рода эпюрами пользоваться не очень-то удобно, так как "глаз все время косит" (в
смысле отклонений от прямых углов), и на этом фоне труднее сконцентрироваться на
основных моментах.
При объяснениях работы интерфейса I2C (и не только), эти "косые" эпюры
применяются авторами сплошь и рядом, что, лично я, не считаю удачным решением.
Гораздо удобнее и легче воспринимаются привычные, "прямоугольные эпюры".
В данном случае (да и в других тоже), переход на них вполне оправдан, так как, при
очень малой длительности формирования фронтов и спадов (на фоне общего масштаба
эпюр), "прорисовать" наклонные участки эпюр просто не возможно (если делать это не в
"огроменном" масштабе).
А это и есть "привязка к жизни".
Так что, ниже, с целью упрощения восприятия информации, я "трансформировал
рисунок 3 в рисунок 4.

Не правда ли, насколько проще стало ориентироваться?


А раз текущая проблема сведена к уровню "коровьего мычания", то можно и еще разок
"на мозги покапать" (для верности).
Прошу прощения за то, что, в принципе, повторяю одно и то же (на разные лады), но это
"коровье мычание" того стоит ("важняк"), и без его уяснения, в I2C лучше даже и "не
соваться".
1. Время задержки такта относительно данных (Тз), есть интервал времени,
ограниченный моментом смены уровней на линии данных (во времени, он
должен следовать первым) и моментом смены уровней на линии такта (во

13
времени, он должен следовать вторым).
Естественно, в этом случае, речь идет о "связке" типа "текущий бит данных и тактовый
импульс под него".
Если "мастер", за время "прохождения" байта, не меняет скорости передачи битов (в
подавляющем большинстве случаев), то все активные перепады (стробы) будут
задержаны относительно соответствующих смен уровней на линии данных, на
одинаковое время (Тз).
На это же время, сместятся вправо (по временной оси) и все не активные (пассивные)
перепады импульсной последовательности такта.
2. Смена уровней на линии данных должна происходить после надежной
фиксации нуля на линии такта.
3. (Кульминация!!!) Двуединые требования пунктов 1 и 2 выполняются при
помощи организации фиксированной задержки на время Тз всех перепадов
(активных и не активных) тактовой последовательности импульсов.
Обращаю Ваше внимание на то, что "до жизни такой" (в принципе, простой и
незамысловатой) я "докатился" путем относительно простых, логических рассуждений,
пусть даже и несколько "громоздких", но, не смотря на это, вовсе не "ущербных".
Это потом, после "шлифовки", будет "бриллиант", а пока и "бесформенный алмаз"
сойдет. Самое главное, что уже есть то, что, в дальнейшем, можно "шлифовать".
Все... С искусственно "локализованным" байтом данных, который записывается в ячейку
памяти "помощника", в общем, разобрались.
Теперь можно заняться и тем, что "обслуживает" процедуру его записи ("петелька-то на
шейке, потихоньку, затягивается" ...).

"Разборки" с "обслуживающим персоналом".


Наиболее внимательные из Вас заметят, что выше речь шла, как-будто бы, о все том же
HT1611/1613.
Если это так, то 5 баллов за внимательность и за работу по "убийству" крылатого
выражения "в одно ухо влетело, в другое вылетело".
Все правильно, в части предмета текущего "копания", аналогия практически полная, с
некоторыми мелкими (не принципиальными), специфическими различиями.
Кто хочет "покопаться" в мелких деталях, милости просим в раздел "Самоучителя...",
посвященный "въезду" в ЖКИ модули на основе HT1611/1613.
Собственно говоря, в свое время, я и создал этот раздел "с дальним прицелом" на то, что
позднее будет "въезд" в "полноценный" интерфейс I2C.
Как видите, дождался.
Теперь пришла пора кое-что объяснить.
То, что Вы читали в разделе, посвященном "въезду" в ЖКИ модули на основе
HT1611/1613 и то, что Вы прочитали сейчас, в принципе (в общем), отражает смысл
работы по интерфейсу I2C, но только этот интерфейс, как бы, "ущербный".
Почему?
А потому, что используется только часть возможностей, а именно: происходит работа
только с данными (в случае работы с HT1611/1613, это адресные запросы к ячейкам
знакогенератора), и только в режиме записи (он установлен разработчиками по
умолчанию, то есть, "намертво"). Обратного "движения" данных (чтения) нет.
Почему такое возможно?
А потому, что у HT1611/1613 "мозгов" (объема памяти) маловато, да и те заложены на
заводе-изготовителе (что-то свое "впихнуть" в эти "мозги" нельзя).
Вот Вам и однонаправленный интерфейс, и "дохлая" (по объему) таблица

14
знакогенератора, и отсутствие подготовительных операций перед началом процедуры
"циркуляции" данных (эти операции просто не нужны).
Управлять такой "куриной памятью" - относительно "плевое дело" и, соответственно,
надобность в каких-то "наворотах" просто отсутствует.
Тем не менее, ругать HT1611/1613 не стоит, так как он, в меру своей "недоношенности",
"справно службу тащит", и "машина" эта, в принципе, не плохая.
А если нужно работать с объемом памяти гораздо большим, чем та, которой
располагают "куриные мозги"?
А если в эту память нужно записать, а затем и считать свою информацию, а не ту,
которую какой-то "дядя", изначально, "намертво вбил" в эти "куриные мозги" (см.
таблицу знакогенератора)?
При первичном анализе возможностей практической реализации этих "грез", сразу же
(на вскидку) возникают 2 "глобальных" вопроса.
1. Раз памяти "запланировано выше крыши", то к ее ячейкам нужно адресоваться, и
адресоваться не слабо, так как объема одного адресного байта совсем не достаточно
(всего-то 256 ячеек памяти).
2. Раз интерфейс двунаправленный, значит должен быть бит выбора режима
чтения/записи.
Все это "добро" должно быть как-то "втиснуто" в байты и "прилеплено" к
"кульминационным" ("центральным") событиям - записи или чтению байта (байтов)
данных.
Опять применяю принцип "разделяй и властвуй".
Адресация к ячейкам памяти "помощника" и сигнал АСК.
Для конкретики, "привяжусь" к объему памяти 8 килобайт (как в 24С64А).
Для адресации к ячейкам такого большого объема памяти, одного адресного байта явно
не достаточно.
Значит нужно задействовать под адресацию не один, а 2 адресных байта, причем,
именно 2 "полноценных" байта, а не "полноценный" байт с "довеском", например, в 2, 3,
4 ... бита.
При работе с м/контроллерами (и с другими "побайтными" устройствами), байт
"дробить" нельзя: либо один байт, либо 2 байта, либо 3 байта и т.д.
И никаких "спариваний слона с мышью" (образ, конечно же, садистский, но суть
отражает четко)!
Двумя адресными байтами, по максимуму, можно адресоваться к 256х256=65536-ти
ячейкам памяти, то есть, ими можно "обслужить" память объемом до 64-х килобайт
(напоминаю, что 1 килобайт равен 1024 байтам).
Нам нужно "обслужить" только 8 килобайт (1024х8=8192 ячейки).
Вывод: под адресацию к 8-килобайтной памяти, будут задействованы следующие
адресные байты: байт младшего разряда адреса - полностью (все 8 его битов) и 5 битов
байта старшего разряда адреса, начиная с младшего его бита (8+5=13. 2 в 13-й степени
есть число 8192).
3 левых бита адресного байта старшего разряда (№№7,6,5) просто не задействуются, а
посему, "мастер" должен в них "заложить" нули.
Итак, все 13 активных битов расставлены "по ранжиру" (по порядку старшинства), а в
трех не активных битах выставлены нули.
Да ведь это же сильно смахивает на двухбайтный регистр!
При работе с программой, эта аналогия пригодится, а пока рановато "дергаться" (всему
свое время).
Следующий вопрос: "Как идентифицировать (разделить) байты"?
Причем, имейте ввиду, что этот вопрос относится к категории "глобальных", то есть, под

15
него "подпадают" вообще все байты, не зависимо от их функциональности.
И в самом деле, если "плотно пристегнуть" (во времени) один байт к другому, то
получится черт знает что (для двух байтов - слово объемом в 16 бит, которому "место на
помойке").
Значит, между ними нужен временной "зазор".
Какой?
В простейшем случае, равный длительности интервала времени "прохождения" бита
(период такта). Этого вполне достаточно.
Практический вывод: байт на линии SDA должен сопровождаться импульсной
последовательностью такта на линии SCL, состоящей не из 8-ми, а из 9-ти тактовых
импульсов.
Если, после этого, оставить все как есть, то получится очень даже не по-хозяйски:
"добро ведь пропадает"!
А нельзя ли на этот 9-й такт "навесить" что-то функционально полезное?
Очень даже можно.
Разработчики пораскинули мозгами, повыбирали из нескольких "полезностей" самую
лучшую, на их взгляд, "полезность", и решили "прицепить" к 9-му такту функцию
подтверждения безошибочности (или ошибочности) приема байта ведомым
устройством.
Назвали этот "наворот" битом подтверждения ACK (да хоть ЁКЛМН, лишь бы работало).
В "глобальном" контексте "идеологии" интерфейса I2C, слово "ведомое" означает то, что
таким устройством может быть как "помощник", так и "мастер" (интерфейс-то
двунаправленный).
Как это выглядит?
Опять "привязываемся" к конкретике, то есть, к случаю, когда ведомым является
"помощник" (режим записи).
В этом случае, происходит следующее: "мастер" выдает "помощнику" байт
(функциональность его "начинки" не важна).
После окончания формирования "мастером" байта (последнего его бита с №0), и в
случае безошибочного приема "помощником" всех его битов, в интервале времени
между "закончившимся" байтом и следующим байтом (напоминаю, что величина этого
интервала времени равна одному периоду такта), "помощник" выдает в линию SDA
нулевой уровень (это и есть бит подтверждения АСК), то есть, в "промежутке" между
байтами (на 9-м такте), происходит смена направления работы интерфейса.
А раз это так, то "мастер" должен "подсуетиться", так как, в противном случае, во-
первых, произойдет объединение двух выходов и возникнет электрический конфликт, а
во-вторых, зачем тогда весь этот "сыр-бор" нужен, если "мастер не воспринимает"
информации, поступающей от "помощника"?
Таким образом, в рассматриваемом случае, "мастер" должен сделать следующее:
1. После окончания "выдачи" в линию SDA бита с №0, он должен перестроиться с
работы "на выход" на работу "на вход" (исключить возникновение электрического
конфликта).
2. После этого, "мастер" должен организовать проверку состояния бита АСК, с целью
ответа на вопрос: "Байт принят "помощником" без ошибки или с ошибкой"?
В зависимости от ответа на этот вопрос, "мастер" должен:
- либо "сказать зер гут" (при АСК=0), перестроиться на работу "на выход" и приступить
к "выдаче" в линию SDA следующего байта (или сформировать стоп-условие и уйти в
ждущий режим, если записывать больше нечего. Об этом - ниже).
- либо "сказать бяка" (АСК=1) и предпринять меры по повторной записи "бракованного"
байта (исправление ошибки).

16
Последнее обеспечивает и безошибочную адресацию к ячейкам памяти "помощника", и
безошибочную запись данных в его ячейки памяти, и безошибочное чтение данных из
них, так как бит АСК является "в каждой бочке затычкой" (сопровождает каждый байт,
вне зависимости от его функциональности).
Для 2-го пункта, есть своя специфика, но я пока не буду "лезть в дебри" (всему свое
время).
Если не учитывать мелких нюансов (подойдет время, учту), то решение этой двуединой
задачи, на аппаратном уровне, обеспечивается перестройкой вывода порта,
подключенного к линии SDA, с работы "на выход", на работу "на вход".
После такой перестройки, вывод порта, подключенный к линии SDA, будет иметь
высокое входное сопротивление.
Это с одной стороны.
С другой стороны, и я обращаю на это особое внимание: "глобальная" концепция
интерфейса I2C, в идеале, предполагает, что к выводам "мастера" и "помощника",
которые подключаются к линиям SCL и SDA, должны быть подключены (внутри
"мастера" и "помощника") коллекторы каскадов с открытым коллектором (или стоки
каскадов с открытым стоком).
Для нормальной работы, такому каскаду нужна нагрузка, а если точнее, то "подтяжка" к
+5в при помощи резистора.
Если, на линии SDA, такой, искусственно созданной, "подтяжки" не будет, то, с учетом
высокого входного сопротивления вывода SDA "мастера" (в том числе и сопротивления
между выводом SDA и +5в), у каскада с открытым коллектором (стоком) просто будет
отсутствовать нагрузка, и работать он "откажется".
Зачем вообще нужен этот "геморрой"?
А затем (и я в этом с разработчиками полностью согласен), чтобы иметь минимум
проблем при организации двунаправленной работы.
И в самом деле, это самый оптимальный и простой вариант организации такой работы,
так как, при изменении направления работы, задействуется всего одна "универсальная"
нагрузка: в одном случае, это нагрузка каскада с открытым коллектором (стоком)
"мастера", а в другом случае, "помощника".
Еще раз обращаю Ваше внимание на то, что только что сказанное относится к идеальной
концепции интерфейса I2C, но жизнь, как всегда, вносит свои коррективы (ниже Вы в
этом убедитесь).
Из этого, пока, следует сделать только тот вывод, что, в идеале, линии SCL и SDA
должны быть подтянуты резисторами к плюсу источника питания.
На это, изначально, и буду ориентироваться.
Вернусь к своим "котлетам".
Какую "подтяжку" использовать: внутреннюю или внешнюю (по отношению к ПИКу)?
С учетом сказанного, ответ однозначен - внешнюю (да и не все порты имеют
внутреннюю подтяжку).
После перестройки вывода порта "мастера" (подключенного к линии SDA) с работы "на
выход" на работу "на вход", внешняя нагрузка, подключенная к линии SDA, становится
нагрузкой каскада с открытым коллектором (стоком) "помощника", который (каскад с
ОК) и формирует уровень АСК на линии SDA.
Обращаю Ваше внимание, что в качестве "мастера" используется PIC16F84A, который
"не адаптирован" под идеальную концепцию интерфейса I2C (что сие означает, поймете
ниже).
Что при этом будет происходить?
При работе с байтом (любой функциональности), транзистор оконечного каскада
"помощника", формирующий уровень АСК, закрыт (соответствует высокому входному

17
сопротивлению вывода SDA "помощника") и внешняя нагрузка, подключенная к выводу
SDA, шунтирует резистор нагрузки выходного каскада той защелки "мастера", выход
которого (каскада) подключен к линии SDA.
Это шунтирование будет незначительным, так как номинал внешнего, подтягивающего
резистора значительно выше номинала нагрузки оконечного каскада защелки, и, как
говорится, "погоды это не делает".
Таким образом, при работе с байтом, все то, что будет "твориться" на линии SDA, будет
определяться только "мастером".
Но как только "мастер" полностью сформирует бит с №0, он перестраивает направление
работы своего вывода SDA на работу "на вход", что соответствует высокому входному
сопротивлению этого вывода.
К линии SDA остается подключенным только внешний подтягивающий резистор
(выход защелки от него отключился).
Это с одной стороны.
С другой стороны, на противоположном конце линии SDA, "помощник не дремлет": он,
на 9-м такте, отпирает, подключенный к своему выводу SDA, транзистор оконечного
каскада формирователя сигнала АСК (в случае успешной обработки байта) и линия
SDA замыкается (через открытый транзистор) на корпус.
В этом случае, через транзистор будет протекать ток, величина которого будет
ограничена внешним, подтягивающим резистором (транзистор работает в ключевом
режиме).
Вот Вам и ноль на линии SDA (сигнал АСК), не смотря на наличие "подтяжки" вывода
SDA "мастера" к плюсу.
Конфликта (объединения выходов) нет, так как вывод SDA "мастера" работает на "вход".
В случае ошибки при записи байта, транзистор просто не открывается, что соответствует
высокому входному сопротивлению вывода SDA "помощника".
Входное сопротивление вывода SDA "мастера" также высокое (работа "на вход"),
следовательно, на линии SDA, через внешний, подтягивающий резистор, будет
"выставлена" 1 (АСК=1).
Вот и вся премудрость.
В принципе, все просто, только, как это не прискорбно, но подобного рода объяснения
я нигде не нашел (может быть плохо искал?).
Если бы я, на данный момент, не знал предмета разговора (через "пинки, фингалы и
голый зад проблемы"), то "с нуля", разобраться во всей этой "абракадабре" было бы
сложновато, даже с использованием документации "Микрочипа" и прочих умных
книжек.
Думаю, что на этом "тернистом пути" (в смысле "пинков", "фингалов" и т.д.) находится
основная масса желающих "въехать" в интерфейс I2C.
В связи с этим, возникает закономерный вопрос: почему, как будто специально,
делается все для того, чтобы люди "пупки надрывали"?
Если это "естественный отбор", то это очень хреновый "естественный отбор", и его
"основоположников" нужно срочно "приводить в чувство" способом принудительного
"сотрясения мозгов".
Так или иначе, но Бог им судья, а у меня своя "копна", которую я и "молочу".
Продолжаю "обмолот урожая".
Ниже Вы видите картинку, которая отражает суть сказанного (без "разрисовки"
переходных процессов при смене уровней).

18
Этой картинкой, в комплексе (и в общем виде), проясняются две "мути": "муть" адресации
"мастера" к одной из ячеек 8-ми килобайтной памяти "помощника", и "муть"
формирования бита АСК.
А вот Вам еще несколько картинок.
На первой из них, в соответствии с концепцией шины I2C, показаны схема
подключения "мастера" (известного нам PIC16F84A) к "помощнику" (м/схеме внешней
памяти 24С64А) и график выбора номинала резисторов внешней нагрузки.
Обращаю Ваше внимание на словосочетание "в соответствии с концепцией шины I2C".
Это не просто так. Это по поводу.
PIC16F84A не "адаптирован" к интерфейсу I2C, в связи с чем возникает некоторый
"бардачек".
Это вовсе не говорит о том, что с помощью PIC16F84A нельзя организовать работу по
шине I2C.
Очень даже можно, но с учетом определенной специфики.
А для того чтобы эта специфика как следует "прошибла мозги", нужно пройти через
процедуру, смысл которой заложен в выражении: "Прежде чем почувствовать что такое
порядок, нужно почувствовать что такое бардак" (все познается в сравнении).
Короче, о "бардаке" я ничего не знаю и не ведаю, и вообще, я пять минут назад "с Луны
свалился".

19
Rвн - резисторы внешней нагрузки.
СэквSCL и CэквSDA - эквивалентные емкости линий SCL и SDA соответственно.
Слово "эквивалентные" отражает суммарную емкость всех тех "паразитов", которые из
линии "кровь сосут" ("режут" верхний "потолок" скорости).
Например, для линии SCL, CэквSCL будет равно сумме входных емкостей выводов SCL
"мастера" и "помощника" (определяется технологией изготовления м/схемы и ее
схемотехникой), плюс монтажная емкость этих же выводов, плюс рассредоточенная
емкость самой линии.
Для линии SDA - то же самое.
В подавляющем большинстве случаев, номинал СэквSCL практически равен номиналу
СэквSDA (разница, конечно же, есть, но незначительная), следовательно, расчитав, по
графику, номинал Rвн для одной из линий, можно смело "цеплять" резистор с таким же
номиналом и на другую линию.
Проще говоря, СэквSCL = СэквSDA и RвнSCL = RвнSDA.
Почему выбор номиналов Rвн существенен?
А потому, что, например, CэквSCL и RвнSCL представляют собой интегрирующую
цепочку, которая дополнительно (за счет емкости линии и монтажной емкости
выводов) затягивает время формирования как фронтов, так и спадов импульсов
(посмотрите на "косые" линии на рис. 3), что, cдвигает верхнюю границу
быстродействия 24С64А вниз.
На низких скоростях обмена информацией между "мастером" и "помощником" это не
существенно (при выборе величины задержки такта Тз, гарантированно
перекрывающей время "затяжки"), но на высоких скоростях обмена, близких к верхней
границе быстродействия "помощника", могут быть всякие "бяки" (сбои или вообще
отказ работы), так как с задержкой такта, в этом случае, "особо не развернешься".
Последний случай встречается достаточно редко, и обычно, скорость работы "связки
мастер - помощник" значительно ниже максимально возможной скорости, что создает
"поле для маневра" с величиной фазового сдвига (задержки).
И еще обращаю Ваше внимание на то, что Cэкв это не атрибут (принадлежность)
принципиальной схемы: в ней и близко не должно быть никаких физических
конденсаторов, подключенных к линиям шины I2C ("Гитлер капут"!!!).
Cэкв это "паразитная" (в том числе и рассредоточеная по линии) емкость, от которой

20
полностью избавиться нельзя.
Ее можно только уменьшить (например, за счет организации более короткого, по длине,
физического соединения и грамотной разработки печатной платы) и не более того.
Таким образом, принципиальная схема "связки мастер - помощник" получается очень
простой (я бы даже сказал - простейшей), но позволяющей, тем не менее, "делать крутые
дела".
Практическое замечание: если происходит работа с низкой скоростью (относительно
"потолка наиболее слабого звена в цепи империализма"), то и "забивать себе голову"
расчетом номинала Rвн не стоит.
Ставьте резисторы по 10 Ком и не ошибетесь.
График опубликован для показа "границ" возможных номиналов Rвн, за которые
заходить не нужно.
"Ломаем" аппаратную часть "связки мастер - помощник" дальше.
Ниже, Вы видите 2 рисунка, иллюстрирующие (на аппаратном уровне) сказанное выше.
Лично я, пытался найти нечто подобное в имеющейся у меня информации по
интерфейсу I2C, но так ничего внятного и не нашел.
Короче, "пошевелил извилиной", в результате чего и "состряпал эти портреты"
(напоминаю, что речь идет о PIC16F84A и 24С64А), с "привязкой" к концепции
интерфейса I2C.

Примечание: на картинках показаны биполярные транзисторы, хотя, по факту, имеют место


быть полевые транзисторы.
Просто биполярные транзисторы, на мой взгляд, как-то лучше воспринимаются (а
может быть и старый стал, живу прошлым ...).
Так или иначе, но это "что в лоб, что по лбу, все едино" (смысл остается одним и тем
же).
В данном случае (см. заголовок рисунка 7), оба задействованных под шину I2C вывода
"мастера" работают "на выход".
После "ревизии" содержимого рис. 7, сразу же "вскакивает" вопрос: "Rн (нагрузка
выходного каскада защелки) и Rвн (внешний подтягивающий резистор), в пределах
каждой линии, параллелятся. Кабы чего не вышло ..." (в смысле перегрузки по току).
Ответ (я об этом упоминал выше, но лишнее напоминание не помешает):
сопротивление нагрузки оконечных каскадов 5-вольтовой логики (в данном случае, Rн)
является низкоомным (порядка нескольких сотен ом).

21
Если, в качестве Rвн, применить резистор с номиналом, например, 10 Ком, то
суммарное значение сопротивления нагрузки выходного каскада защелки (а Rвн
является его частью) уменьшится, но очень не значительно.
С учетом того, что оконечный каскад защелки нормально работает с токами аж до 25 ма,
это "запараллеливание" для него - "как слону дробинка", даже в самом невыгодном
случае, когда транзистор выходного каскада защелки будет постоянно открыт.
Реально же, режим работы выходного каскада защелки значительно "облегчается" за
счет того, что он управляется импульсами (когда транзистор закрыт, то ток, проходящий
через него и через его нагрузку, имеет очень малое значение).
Короче, параллельное соединение Rн и Rвн к плохому не приведет ("граница может
спать спокойно").
Смотрим на "помощника".
По обеим линиям шины I2C, он работает "на вход", так как оба транзистора закрыты.
В принципе, по этой причине, их можно было бы вообще не рисовать.
Что такое "Ключ"?
Это внутренний коммутатор "помощника".
В данном случае, он разрешает обработку данных (пропускает их в "дебри" 24С64А).
Следующий случай: передача сигнала подтверждения (АСК) "помощником" и его
прием "мастером":

В этом случае, вывод порта "мастера", подключенный к линии SDA, работает "на вход".
Во временном "промежутке" между битом №0 предыдущего байта и битом №7
следующего байта (на 9-м такте), транзистор оконечного каскада устройства
формирования уровня АСК открывается (в случае безошибочного приема байта
"помощником") и линия SDA (со стороны "помощника"), через открытый транзистор,
коммутируется на корпус.
На линии SDA устанавливается ноль.
В случае ошибки, транзистор как был закрыт, так закрытым и останется (ноль реакции).
В любом случае, на 9-м такте, "мастер" должен проанализировать (опросить) состояние
вывода порта, подключенного к линии SDA для того, чтобы решить, "как жить дальше"
(в какой сценарий уходить, см. выше).
При этом, подтягивающие резисторы порта "мастера", на время исполнения процедуры
анализа состояния бита АСК, лучше (но не обязательно) отключить, так как

22
подтягивающий резистор вывода порта, подключенного к линии SDL, уменьшает
суммарное сопротивление "подтяжки" (параллельное соединение резисторов внешней и
внутренней подтяжки).
В основном, это ничем особо плохим не закончится (внутренний, подтягивающий
резистор достаточно высокоомный), но зачем нужна, пусть и малая, но дополнительная
нагрузка на транзистор оконечного каскада устройства формирования уровня АСК,
если от этого можно избавиться?
Да и порядка больше.
Естественно, что в этом случае речь идет о выводе порта, который (порт) имеет
внутреннюю подтяжку (например, порт В).
Если вывод входит в состав порта, не имеющего внутренней подтяжки (например, порт
А), то и проблемы нет.
В данном случае, во избежание "глюка" "помощника", ключ коммутатора разомкнут (бит
АСК не обрабатывается "помощником").
С основным, кажется, разобрался, но "вскакивает" очередной и очень хитрый вопрос:
"Каковы функции транзистора, подключенного к линии такта со стороны помощника"?
С учетом концепции шины I2C и соответствующей этой концепции принципиальной
схемы (см. выше), массово тиражируемой источниками информации по интерфейсу
I2C, наличие внешнего подтягивающего резистора на линии SCL означает то, что к
линиям шины I2C, с обеих сторон, должны быть подключены каскады с открытым
коллектором (стоком).
На рис. 7 и 8 Вы их, в "помощнике", и видите (на счет "мастера", "толковище" будет
ниже).
Изначально, "рожая" эти транзисторы, я исходил именно из этого предположения.
К транзистору, формирующему уровень АСК, претензий нет: он стоит по делу и нужен,
а вот функции транзистора, подключенного к линии такта, совершенно "мутны".
А раз это так, то вспоминаю крылатую фразу "доверяй, но проверяй".
"Хулиганить" буду "по полной программе" (авторитеты - по фигу). Как говорится,
"безумству храбрых поем мы песню"...
Все внимание - на линию SCL. Следите за ходом рассуждений.
В рассматриваемом случае, помощник, уже по определению, является "рабом"
(ведомым), так как он не вырабатывает свой такт.
Исключением является кратковременное "тявканье" во время выдачи сигнала АСК, но
это уже другая "епархия" (линия SDA), которая к транзистору на линии SCL (в
"помощнике", см. схему) отношения не имеет.
По линии SCL, импульсы "циркулируют" только в одном направлении: от "мастера" к
"помощнику".
Тогда на кой черт нужен транзистор, подключенный к линии SCL со стороны
"помощника", и, соответственно, внешний подтягивающий резистор???
В данном случае (подчеркнуто не зря), внешний, подтягивающий резистор на линии
SCL нужен так же, как корове пятая нога, ведь линия SCL и без него уже подтянута к
плюсу источника питания через резистор коллекторной нагрузки выходного каскада
защелки, выход которой "на веки вечные" подключен к выводу порта, обслуживающему
линию SCL (этот вывод постоянно работает "на выход").
"Помощник", в части касающейся линии SCL, никогда не будет ведущим, и он работает
только "на вход".
Из этого следуют незамысловатые, "революционные", для конкретного случая, выводы :
- транзистор "помощника", подключенный к линии SCL - расстрелять,
- подтягивающий резистор линии SCL - расстрелять.
Получилось вот что:

23
"В чем собака порылась"?
Объясняю.
Подавляющая часть авторов информации по работе м/контроллеров с м/схемами

24
внешней памяти по интерфейсу I2C (а у меня создается такое впечатление, что вообще
все), просто бездумно и без учета реалий, тиражируют типовую, принципиальную
схему организации интерфейса I2C, составленную под "полноценную" его концепцию.
Имеется факт непонимания следующего "постулата": м/схемы памяти
последовательного типа (24Схх и подобные), в части касающейся линии SCL, могут
работать только в режиме ведомого (линия SDA не в счет из-за смен направлений
работы).
Под словом "полноценный" следует понимать возможность взаимообмена между
устройствами (в ходе исполнения программы) функциями "мастера" и "помощника"
(ведущего и ведомого), причем, по обеим линиям, а не "связку" типа "вечный начальник
- вечный раб" (в части касающейся линии SCL), что и имеет место быть в
рассматриваемом случае.
"Полноценный" интерфейс I2C должен обеспечивать возможность "циркуляции"
тактовой последовательности импульсов по линии SCL в обеих направлениях.
"Tуманность" ситуации усугубляется тем, что, в случаях подобных рассматриваемому,
совершенно лишний, внешний, подтягивающий резистор линии SCL, как говорится,
"общей погоды не портит", так как его номинал значительно превышает номинал
нагрузки оконечного каскада защелки, выход которой подключен к линии SCL со
стороны м/контроллера.
Внешний подтягивающий резистор на той или иной линии (SCL, SDA) нужен только в
том случае, когда, в ходе исполнения программы, осуществляются смены направлений
передачи (приема) сигналов, с задействованием каскада с общим коллектором или
стоком.
В этом случае, внешний подтягивающий резистор является нагрузкой этого каскада,
обеспечивающей его нормальную работу, и его (резистора) применение оправдано (он
просто необходим).
Посмотрите на рис. 10 и 11.
Для линии SDA, внешний подтягивающий резистор обязательно нужен, так как, в
противном случае, "помощник" просто не сможет сформировать сигнал АСК,
"привязанный" к 5-вольтовым уровням нуля и единицы.
Для линии SCL, внешний подтягивающий резистор не нужен, так как подтяжка
осуществляется и без него, при помощи резистора нагрузки оконечного каскада
защелки.
При этом, обращаю Ваше внимание на то, что все эти рассуждения относятся к
м/контроллерам, не "адаптированным" к работе с интерфейсом I2C (к ним относятся
PIC16F84A и PIC16F628).
Что значит "не адаптированными"?
Это значит то, что в их состав не входят каскады с открытым коллектором (стоком),
требующиеся для "полноценной" реализации полномасштабной концепции интерфейса
I2C.
Отсюда и возникает "разнобой", связанный с "нестыковкой" их схемотехники с
требованиями концепции интерфейса I2C, пример которого ("разнобоя") приведен
выше.
Это плохо?
Нет, совсем не плохо (в пределах не очень "крутых" задач), а в основном, даже и проще.
Скажу больше: м/схемы памяти, хотя и работают по интерфейсу I2C, но также
полностью "не вписываются" в его концепцию, так как, в части касающейся линии SCL,
они есть устройства ведомые и своего такта формировать не могут (не могут быть
ведущими по определению).
Это плохо?

25
Вовсе нет.
В пределах "делегированных им полномочий", они "справно службу тащат" (а от них
чего-то уж очень "крутого" и не требуется).
Примерно то же самое можно сказать и о большинстве других типов "помощников".
При помощи чего можно реализовать полномасштабную концепцию интерфейса I2C (с
возможностями по-максимуму)?
При помощи "адаптированных" под этот интерфейс м/контроллеров.
Причем, "связка мастер - помощник" должна состоять только из "адаптированных" под
интерфейс I2C м/контроллеров (плюс периферия к ним из того, что попроще), любой из
которых может быть ведущим.
В этом случае, концепцию интерфейса I2C можно реализовать по максимуму.
Вот какие "заоблачные дали" (да уж, развернуться есть где ...) и вот какой манящий
"приз", привязанный к верхушке высоченного столба.
Давайте будем реалистами: "халява" здесь в упор не пройдет. Чтобы заполучить такой
"приз", нужно упорно и по-умному лезть на этот столб, причем, не исключено, что и
несколько раз больно "грохнуться" с него (а как же без этого?).
Если сразу, с дуру, "падать" на этих "информационных монстров", то ведь "сожрут, как
пить дать".
Кстати, авторы подавляющей части информации по интерфейсу I2C, как-то по-свойски,
просто и незамысловато, сразу и без подготовки, предлагают залезть на этот столб.
Такая святая наивность (или что-то другое?) меня до глубины души умиляет, и мои
губы, вне зависимости от сознания, рефлекторно расплываются в идиотской улыбке.
Да ... богата наша страна неординарными людьми (аж гордость грудь распирает). Куда
уж там каким-то "америкашкам" или "япошкам" с нами тягаться. В момент шапками
закидаем и бантик сверху привяжем.
А нам, ординарным и убогим, ничего другого не остается, как заняться чем-нибудь
попроще.
Прежде чем добраться до "высших сфер", "боевая подготовочка" и "тренированная
извилина" нужна.
Так что, давайте упорно "свою копну молотить" (альтернативы этому нет).
Итак, по-отдельности, с передачей байта, с адресацией к ячейке памяти "помощника", c
формированием сигнала АСК и с принципиальной схемой, более-менее разобрались.
Какие "кирпичики" еще имеются в наличии?

"Режимный" байт.
Ранее предполагалось, что режим записи заранее установлен.
Пришла пора задать вопрос: "Каким образом"?
В части касающейся рассмотренного, "вклинить" куда-то бит установки режима чтения
или записи не представляется возможным.
Теоретически, можно его "засунуть", например, в бит старшего разряда старшего байта
адресного запроса, но, во-первых, это потеря максимально возможного объема памяти, а
во вторых, куда девать еще 3 бита адресного запроса выбора м/схемы?
Значит, хочешь - не хочешь, но под это дело нужно выделять еще один байт.
Я его называю "режимным", хотя в нем и имеется только один режимный бит (но зато
важный), а остальное - адресация.
Можете "обозвать" его еще как-то, а я буду называть его "режимным".
Естественно, для одного бита, выделять целый байт будет слишком "жирно", но ведь
нужно еще и адресоваться к конкретной микросхеме памяти (выбор активной м/схемы),
в случае подключения к шине I2C нескольких м/схем памяти (см. выше)?
А это целых 3 бита.

26
3 (адресация)+1(чтение/запись) = 4 бита.
Остаются 4 "свободных" бита.
К чему бы их "приткнуть" (жалко ведь, что добро пропадает)?
Разработчики, не мудрствуя лукаво, "влепили" в них код выбора "глобальной"
функциональности (это определение - моя фантазия).
Для м/схем памяти последовательного типа, он такой: 1010.
Приняв этот код выбора "глобальной" функциональности, м/схема памяти "соображает",
что "мастер" "домогается" именно ее функциональности (намерен работать с внешней
памятью), а не какой-то другой "железяки", реализующей другую функцию.
Дело в том, что к шине I2C, наряду с м/схемой (м/схемами, если к шине I2C их
подключено несколько) памяти последовательного типа, может быть подключена
м/схема (м/схемы) последовательного типа с другой (нежели память)
функциональностью.
Так вот, этот 4-битный код и определяет, какой именно "глобальной"
функциональности "домогается" "мастер" от кучи своих "помощников".
Если "помощник" всего один (как в нашем случае - м/схема памяти), то код 1010 просто
фиксируется "на веки вечные" ("мастер", после любого старта, выдает только этот код).
Вот и вся премудрость.
Получилась такая картинка:

Код функциональности (1010) "застолблен намертво" и не меняется.


В случае подключения к шине I2C одной м/схемы 24С64А, уровни битов A2, A1, A0
проще всего принять равными нулю, что Вы и видите.
А раз это так, то выводы м/схемы 24С64А с названиями A2, A1, A0 соединяются с

27
корпусом.
Можно, например, подать на эти выводы единицы (соединить с +5в), но в этом случае,
"мастер" должен сформировать "режимный" байт с единичными уровнями битов с №№
1,2,3.
И вообще, можно назначить любую трехбитную комбинацию, но зачем нужно мудрить
с распайкой выводов A2, A1, A0? Проще закоротить все эти выводы на корпус, а в
соответствующих битах выставить нули, что и имеет место быть.
С битом чтения/записи (№0) еще проще: выставили 1 - будет чтение, а выставили 0 -
запись.
Все, баста, с этим байтом разобрались.
Пошли дальше.

Старт-стопные условия.
Итак, имеет место быть некая (конкретика будет позднее) "пачка" ("набор") байтов, но она не
может быть "безразмерной" по объему по той простой причине, что, для "мастера",
обмен сигналами с "помощником" вовсе не есть самоцель (он не может все время
работать на него, и "свет клином на нем не сошелся").
Есть и другие, не менее важные дела (например, обработка считанного байта и т.д.).
Таким образом, "мастер" работает с "помощником" не постоянно, а периодически, что
предполагает наличие неких массивов байтов, "циркулирующих" по шине I2C, причем,
речь идет о байтах любого функционального предназначения.
А это, в свою очередь, предполагает наличие, достаточно протяженных во времени,
"промежутков" между этими массивами, то есть, наличие режима ожидания
следующего массива байтов (ждущий режим).
Как быть, например, в том случае, когда в предыдущем массиве байтов производится
чтение, а в следующем - запись?
Если не предпринять каких-то "идентификационных" ("разграничительных") мер, то вся
работа "пойдет коту под хвост".
Вывод: нужно как-то "пометить" начало и конец каждого массива байтов, с целью их
идентификации, то есть, отделения одного массива байтов от другого, а заодно и
продумать, что будет "твориться" на шине I2C во время прохождения временных
"промежутков" между этими массивами (в режиме ожидания, или в пассивном режиме.
Можно назвать как угодно).
В этом случае, речь идет о так называемых "старт - стопных" условиях, грамотный выбор
которых "прихлопывает" сразу обе сформулированные выше задачи.
Собственно говоря, простой анализ приведенных выше эпюр, наталкивает на
однозначную мысль о том, что, в режиме ожидания (или в ждущем режиме), на линиях
SCL и SDA должны быть выставлены единицы.
А раз это так, то условием старта (начала массива байтов) будет смена уровня ждущего
режима (на линии SDA) с 1 на 0, а условием стопа (конца массива данных) будет смена
уровня на линии SDA с 0 на 1 (переход в ждущий режим).
В последнем случае, по той простой причине, что в конце байта выдается бит АСК,
стоп-условие должно быть "привязано" к уровню бита АСК.
Если последний байт массива байтов принят без ошибок, то вот Вам и гарантированный
0, который, при стопе, cменяется на 1.
В этом, в основном, и заключается "глобальная стратегия" (смысл, замысел) процедуры
старт-стопа.
Как это реализуется? А вот так:

28
Режим ожидания.
На линиях SCL и SDA "мастер" выставляет единицы.
Пока они там "торчат", "мастер" делает какие-то другие дела (коих у него великое
множество), не связанные с обращением к внешней памяти.

Старт.
"Мастеру" "взбрело в голову поковыряться" во внешней памяти (что-то из нее считать или что-
то в нее записать).
Чтобы "помощник" понял, что "мастер" его "домогается", "мастер" должен сформировать
старт-условие, то есть, "мастер" должен сменить на линии SDA единицу на ноль, при
наличии единичного уровня на линии SCL (см. приведенные выше рассуждения и
рисунок).
Это и есть старт-условие.
После старта, "мастер" должен "озаботиться" формированием соответствующей
импульсной последовательности такта на линии SCL.
Так как величины тактовых интервалов времени (Ттакт) на обеих линиях одинаковы
(такт на линии SCL только задержан относительно такта на линии SDA, и не более
того), то "вскакивает" вопрос о том, когда формировать первый строб.
Ответ однозначен: спустя время Тз после начала бита №7 (см. информацию,
изложенную выше).
Но есть одно "но": единицу на ноль на линии SDA мы сменили, и этот ноль, по
здравому разумению, должен там какое-то время "поторчать" (а иначе зачем
производить такую смену?).
Какое время?
В принципе, это время может быть очень коротким, так для формирования старт-
условия много времени не требуется (напоминаю, что старт-условие есть перепад от 1 к
0), но с точки зрения максимальной простоты программной реализации устройства,
лучше соблюдать "тактовые правила игры" в том смысле, что все перепады на линиях
SDA и SCL должны быть "жестко привязаны" к интервалам времени кратным Ттакт/2.
Разница заключается только в том, что "пачка" такта задержана относительно "пачки"
данных на время Тз.
С учетом этого, самый оптимальный (с точки зрения простоты программной
реализации) вариант старт-условия выглядит так, как это изображено на картинке.
Что в "сухом осадке"?
А в "сухой осадок выпало" следующее правило: хочешь надежно и просто (в

29
программном и в других смыслах) "стартануть"?
На старте, дополнительно задержи начало тактовой последовательности импульсов на
время Ттакт/2.
Слово "дополнительно" означает то, что задержка Тз это само собой разумеющееся, так
как задержка Тз применяется абсолютно ко всем перепадам импульсных
последовательностей, передающихся по линии SCL.
Таким образом, суммарная задержка первого спада (от 1 к 0) на линии SCL
относительно старт-условия (первого спада на линии SDA), должна составлять Тз +
Ттакт/2.
Особо обращаю внимание на то, что эту суммарную задержку нужно произвести только
при формировании старт-условия, а далее "погоду будет делать" только задержка Тз.
Итак, что мы имеем по старт-условию?
А имеем мы то, что и волки сыты (соблюдены условия работы по интерфейсу I2C), и
овцы целы (минимальное количество программных и аппаратных проблем).
Еще один "глобальный" (общий) вывод : время Тз и время Ттакт/2 должны быть
"жестко привязаны" к машинным циклам "мастера", и любая из этих задержек не должна
быть меньше одного машинного цикла.
И это естественно, так как к ним, по определению, "привязаны" все перепады (то есть,
такт).
Весь вопрос состоит только в кратности, то есть, в целом количестве машинных циклов,
"укладывающихся" в Тз или Ттакт/2.
Эта кратность может быть различной (зависит от многих причин), и она определяется в
каждом конкретном случае.

Стоп.
Чтобы "помощник понял", что "его услуги мастеру больше не требуются", и что "мастер" хочет
перевести его в ждущий режим, "мастер" должен сформировать стоп-условие.
Делается это так.
Последний импульс массива байтов (9-й) формируется не так, как формировались
предыдушие тактовые импульсы: его единичный уровень затягивается (спад не
формируется) на все время ждущего режима.
В результате этого, получается "здоровенный" 9-й импульс (его протяженность зависит
от последующего времени нахождения в ждущем режиме).
Теперь "мастеру" только нужно, в момент окончания АСК, выставить на линии SDA
единицу (опять же, на все время ждущего режима).
Это и есть стоп-условие.
Особенности: выше предполагалось, что стоп-условие формируется по окончанию
формирования бита АСК.
В большинстве случаев, это так и происходит, но есть и специфика ("навороты"), речь о
которой пойдет позднее.
В ждущем режиме, на линиях SCL и SDA будут "торчать" выставленные "мастером"
единицы, а "помощник", "как медведь зимой, уйдет в спячку".
Он будет "спать" до тех пор, пока "начальство не окликнет" (старт-условие).
Все. Баста!
Первый этап "въезда" функционально закончен.
Как там чувствует себя наш амнезийный боец?
Ага, в глазах появились проблески разума, но и дебильности еще предостаточно.
Будем "лечить" дальше, вплоть до электрошока.
Общие замечания по методологии "въезда" (или "взлома", это одно и то же).
Прошу вдуматься в "глобальную" стратегию того, что Вы прочитали.

30
Худо-бедно (Вам судить), но я постарался выстроить строго последовательную цепочку
рассуждений, порядок следования которых взят "не с бухты-барахты" (Фигаро здесь,
Фигаро там), а "привязан" к изначально выставленным приоритетам, то есть, к плану,
ориентированному на соблюдение принципа "от простого к сложному".
Пока еще рано говорить о реализации этого плана, но самая нудная его часть уже
позади.
В этом подразделе, я только скурпулезно разглядывал под лупой отдельные "кирпичи",
из которых в дальнейшем предстоит построить нечто такое-эдакое (есть только общие
контуры, но ничего, определимся по ходу дела) и совершенно сознательно не "дергался"
по поводу преждевременного начала "строительства", так как я "волк стреляный" и
прекрасно (на собственной "шкуре") знаю, чем обычно заканчиваются такие "дерганья".
Одно из условий успеха, на мой взгляд, состоит в том, что нули с единицами (и прочие
атрибуты цифровой техники) должны быть не "мертвыми" (вот беда, так беда), а
"живыми".
Пока они не станут "живыми", с конструированием, на мой взгляд, просто не стоит
связываться, так как "мертвяк", он и есть "мертвяк" (тоска и безвременная кончина).
Вот когда появляются "глюки" в виде "живых существ" (естественно, в воображении),
тогда, как это ни странно, ремесло превращается в искусство, и, соответственно,
рождаются творения (без кавычек).
Для "оживления" нулей и единиц, на мой взгляд, все средства хороши (победителей не
судят), и тем более, что в этих средствах нет ничего криминального.
Следующий подраздел будет продолжением этого подраздела.
В нем я буду строить, из "просканированных" выше "кирпичей", некое "сооружение"
(пока не знаю какое, но думаю, что не "рогатое". Жизнь покажет).
Короче, буду собирать "до кучи" все то, что "нарыл".

31