Сниффер шины i2c arduino

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

Статья будет своего рода шпаргалкой, для того чтоб быстро узнать I2c адрес устройства. Я приведу два примера, один для того чтоб узнать адрес при помощи arduino, а второй способ будет, чтоб найти адрес устройства через raspberry pi.

Итак чтоб узнать i2c адрес на arduino нужно подключить устройство к пинам SDA и SCL они у arduino находятся A4(SDA) и A5(SCL).

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

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

Сниффер шины i2c arduino

Со сканером i2c на ардуино мы я думаю разобрались, теперь давайте бегло разберемся как отсканировать шину на raspberry pi.

i2c у raspberry pi находится на пинах PIN3 и PIN5

Видео:Декодер протоколов | Часть первая I2C снифферСкачать

Декодер протоколов | Часть первая I2C сниффер

I2C-сниффер

Начало

Под рукой валялись только пара атмег8 и я решил почему бы не использовать их. Далее, встал вопрос схемы сниффера.

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

Вкратце, о самом интерфейсе. В I2C (TWI по-атмеловски) используется два провода — SCL и SDA. Первый отвечает за тактирование сигнала, второй за передачу непосредственно информации. Также интерфейс располагает состояниями СТАРТ и СТОП.

Так вот, первая моя мысль была — взять щуп и с одной стороны подключить его к ноге внешнего прерывания на atmega8 с другой на линию SDA и ловить передний фронт, и по прошедшему времени определять 0 или 1. Очевидно, что работать это должно было очень плохо, так как не отрабатывался корректно сигнал СТОП.

Вторая мысль была сделать все то же, но прерывание ловить на линии SCL, и по прерыванию читать линию SDA, подключенную на обычную цифровую ногу. Здесь все выглядело уже более жизнеспособно, кроме того же состояния СТОП, но я решил попробовать собрать на макетке и посмотреть что же будет.

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

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

В порт потекли нули и единички, но сразу стало очевидно, что данные некорректные — их было гораздо меньше ожидаемых и они менялись при повторении одного и того же запроса. В процессе выяснения причин все свелось к тому, что данные теряли из-за обращения к uart интерфейсу, который, к слову, работал на максимальной стабильной скорости 38 кбит/с, при этом сам I2C работал на 100 кбит/с. Поднимать скорость работы UART не представлялось возможным ввиду отсутствия кристалла необходимой частоты, чтобы перевести uart на допустимую скорость. Следовательно нужно было убирать работу с uart из прерывания. Получил что-то следующее:

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

На верном пути

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

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

Читайте также: Что такое взрывная накачка шин грузовых автомобилей

В итоге получился следующий код:

Мастер устройство подключается на аппаратный I2C атмеги, исполняющее устройство подключается на любые 2 цифровые ноги, одна из которых работает в режиме SCL, другая — SDA. Все, что делает приведенный выше код — это получает по I2C прерывание и вызывает аналогичное состояние на программном интерфейсе, при этом в uart записывается служебная информация, помогающая понять что происходит. Выставленные задержки подбирались для конкретного устройства и могут несколько отличаться для других. В итоге получаем вполне добротный сниффер.

Если кому-нибудь будет интересно, то исходники можно взять с гитхаба.

Видео:Введение в шину I2CСкачать

Введение в шину I2C

I2C сканер на Arduino

Автор: Сергей · Опубликовано 26.10.2017 · Обновлено 27.09.2019

В этой статье расскажу как с помощью Arduino сделать I2C сканер, в качестве примера определю адрес LCD1602 дисплей, работающего по интерфейсу I2C.

Сниффер шины i2c arduino

I2C сканер на Arduino

Немного теории, I2C — это протокол, который позволяет различным устройствам взаимодействовать друг с другом используя одну шину данных SDA и SCL (всего два проводника), так же, для каждого устройства присваивается свой уникальный адрес (максим 127 устройств). Поменять адрес устройства нельзя, он намертво вшит в микросхему, но некоторые производитель предоставил возможность изменять адрес в небольшом диапазоне, это дает возможность подключить несколько одинаковых устройств (с одинаковым чипом) к одной шине.
Иногда, нет возможности найти документацию на микросхему или микросхема не имеет адрес схожий от документации (такое то же бывало), тогда поможет данный скетч. В примере используется Arduino UNO и LCD модуль I2C (который имеет брак и другой адрес, не 0x27), так-же, интерфейс I2C работает только на определенные выводах (в arduino UNO это A4 и A5), приведу таблицу подключения для различных платформ Arduino.

Сниффер шины i2c arduino

Собираем принципиальную схему

Сниффер шины i2c arduino

Открываем среду разработки IDE Arduino, копируем скетч и загружаем его в платформу Arduino.

Видео:Видеоуроки по Arduino. I2C и processing (7-я серия, ч1)Скачать

Видеоуроки по Arduino. I2C и processing (7-я серия, ч1)

Сниффер/эмулятор I2C и 1-wire

Это первая версия устройства, и она не лишена недостатков. В т.ч. иногда девайс зависает по непонятным причинам. Если честно мне лениво было отлавливать этот баг. Зависает не часто и решается перезагрузкой.

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

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

И вот, дабы упростить/ускорить процесс отладки, я решил сделать i2c сниффер. Первоначально задача была такая: прослушивать I2C линию и отправлять лог в компьютер. Когда это было реализовано, выяснилось, что в Tiny2313 осталось еще полно свободного флеша. Поэтому был придуман дополнительный функционал.
Вот, что в итоге получилось:

Сниффер шины i2c arduino

Вид у него не самый гламурный, да в этом и не было необходимости.

— Обмен данными с компьютером через UART. Сейчас подключается к COM порту, что не очень удобно (приходится отдельно подрубать питание). Во второй версии сделаю подключение по USB на базе FT232.

— В режиме i2c сниффера уверенно работает при скорости обмена (частоте SCL) до 50кГц. В этом режиме он записывает всю активность на линии в лог, который в фоновом режиме выкидывается на комп. Вместе с каждой записью в лог пишется время.

Первым делом я расскажу про то, как устроен i2c сниффер, ибо это тот функционал, ради которого задумывалось устройство. Сниффер я опишу чуть подробнее, чем остальные функции. Он реализован на базе USI, и будет ещё одним примером использования этой приблуды (по другому USI не назовёшь).

Потом я расскажу про мастер-режим. i2c мастер тоже реализован на USI. 1-wire полностью программный, и ничего особо интересного из себя не представляет.

Но сначала, общий экскурс:
За питание отвечает преобразователь на 78L05. Или, как я уже сказал, можно подрубить 5В с отлаживаемого устройства. Вообще, это конечно неудобно. В следующей версии будет USB. На питании стоят защитные диоды, поэтому спалить девайс проблематично.

На связи у нас max232. Моя разводка может показаться слишком мелкой (so16 и 0805 кондеры почти влотную к нему), но по-другому оно туда не влезало.

Читайте также: Куда используется резиновая крошка от переработки шин

Кварц 20МГц. Можно было взять и меньше, например на 16. Высокая скорость необходима для быстрой работы конечного автомата i2c сниффера. Корпус кварца я заземлил, так, на «всякий пожарный».

ATTiny2313 правит бал. Во-первых это один из немногих обладателей USI. Во-вторых он может разгонятся до 20МГц. Разъём для программирования я не вывел, поэтому придётся подпаивать проводки.

На линиях SDA и SCL (это PB5 и PB7, соответственно) есть подтягивающие резисторы по 4.7к. Они подключены к ножке PB6, которая, по команде с компа подключается к питанию, обеспечивая внутреннюю подтяжку.

Ещё есть места для четырёх светодиодов, которые, в итоге не пригодились.

Сниффер шины i2c arduino

Крупнее

i2c сниффер.

i2c сниффер можно было реализовать полностью программно, но на USI это намного удобнее. Главным образом потому, что USI имеет встроенный Start condition detector, да ещё и с отдельным прерыванием.
Вот только проблема в том, что USI сам-по себе бесполезный кусок конечного автомата, и часть логики придется реализовать программно. С одной стороны это не удобно, а с другой — есть возможность замутить, например, сниффер, который на обычном TWI сделать невозможно.

По логике протокола i2c обмен данными, при передаче байта, проходит в двух направлениях. Если мы передаём байт, то нужно передать 8 бит «туда», и прочитать 1 бит «оттуда». Если читаем, то наоборот.
В случае-же сниффера, не существует «туда» и «оттуда». Есть только одно направление — «мимо». Это несколько облегчает задачу. Нам нужно всего-навсего слушать линию и складывать данные в буфер. Из этого буфера они будут передаваться на компьютер.

Вся движуха на линии делится на четыре типа:
0x1 — Старт детектед
0x2 — Стоп детектед
0x4 — Байт + ACK
0xC — Байт + NACK

Запись для каждого события занимает 4 байта. Первый (Старший) байт — это код события (те-самые 0x1,0x2. ). Во втором данные. Для первых двух событий данные не нужны, тогда второй байт = 0. Последние два байта — значение таймера. Он запускается, как только будет пойман первый start-condition, и сбрасывается по команде с компьютера. Период одного «тика» таймера — 1мс. Он может считать чуть больше минуты, этого более чем достаточно для отлова всяких повторов и других неведомых вещей, которые иногда творятся на линии.

Сниффер шины i2c arduino

Если бы мы решили ловить Start condition программными средствами, то пришлось-бы заводить ножку SDA на прерывания, и уже там определять старт это, или просто SDA переключилась. А при помощи USI такая задачка решается просто: включаем прерывание USI START и ждём…

Вот так выглядит обработчик этого прерывания:

Первым делом мы сбрасываем флаг USISIF. Это нужно сделать как можно быстрее, ибо, пока флаг поднят, USI будет зажимать линию SCL. Затем мы запихиваем в счётчик USICNT 0x0F, и пишем в переменную USI_recv_state 2. Это подготовка к приёму данных (Знаю, сейчас похоже на черную магию, но потом станет понятнее). Проверяем, если таймер ещё не запущен, то сбрасываем его и запускаем.

Для опредения stop-condition нам предоставили почти тоже самое, что и для start. Только прерывание пожадничали. Поэтому пришлось добавить в цикл программы проверку флага USIPF.

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

Самое интересное — поймать данные. Целых 9 бит. USI у нас настроен так:
USICS1 = 1; USICS0 = 0; USICLK = 0 — это значит, что при каждом положительном фронте на SCL, регистр данных USIDR будет сдвигаться, и в него будет записываться бит с линии SDA. А счётчик USICNT будет тикать на каждый фронт SCL.

Сниффер шины i2c arduino

А вот и чёрная магия:

При старте мы загружаем в USI_recv_state значение 2, а в счётчик (USICNT) — 0x0F. Таким образом переполнение счётчика (и прерывание USI) произойдёт, как только линия SCL упадёт в 0.

В прерывании (Переполнение счётчика) мы проверяем USI_recv_state — определяем на каком этапе приёма мы сейчас находимся.

Если USI_recv_state = 2, то нужно подготовится к приёму данных. Очищаем счётчик, чтобы он мог протикать все 16 тактов. И не забываем обновить значение USI_recv_state (теперь записываем 0), чтобы в следующий раз корректно обработать прерывание.

Читайте также: Шины фредештайн ультрак сессанта

Потом, в течении 16 тактов счётчика (по одному такту на каждый перепад линии SCL) USI работает автоматически, не отвлекая программу по каждому пустяку. При этом, на каждый положительный фронт SCL, бит с шины проталкивается в регистр USIDR. Таким образом, к тому моменту, как случится прерывание, в регистре уже соберётся весь байт.

Если USI_recv_state = 0, то можно забирать данные (пока-что во временную переменную), и готовится к чтению девятого бита (ACK). Счётчик переполнился на заднем фронте восьмого импульса SCL, а ACK можно читать только на переднем фронте следующего импульса. Поэтому нужно протупить ещё один такт счётчика — записываем 0x0F. Ну, а в USI_recv_state записываем 1.

Если USI_recv_state = 1, значит можно читать ACK и загонять данные в буфер. А вот следующий фронт нам придётся пропустить. Для этого загоняем в счётчик 0x0F, а в USI_recv_state число 2.

Сниффер шины i2c arduino

Потом, если по линии побегут ещё данные, цикл повторится сначала.
Отправка данных в компьютер тоже автоматизирована. Как только в буфер попадают данные, запускается конечный автомат на прерывании UDRE (UART Data Register Empty). Как только на линии происходит какое-то событие, в буфер добавляются данные и сдвигается указатель, по которому происходит запись. Параллельно с этим данные из буфера отправляются в UART.

i2c мастер.

У мастера есть две основные функции — чтения данных из слейва и запись в него.
Отладчик в мастер-режиме не следит за арбитражем. То есть предполагается, что на линии только один мастер.

Обмен данными с отладчиком в этом режиме происходит по такой схеме:
1) Посылаем команду 0x31 — переход в мастер режим.
2) Посылаем 0x34. Эта команда говорит отладчику, что сейчас в UART прилетит куча данных — список действий, который отладчик должен выполнить.
3) Сразу за командой 0x34, посылаем размер (в байтах) этого списка действий.
4) Посылаем весь список.
5) Посылаем команду 0x35 — выполнить список.

После этого отладчик начинает последовательно выполнять команды из списка. На место выполненной команды записывается отчёт. То есть, после выполнения команды «Передать байт 0x38», на её место запишется, например «Передан байт 0x38, получен NACK».
И команда, и отчёт занимают два байта. Логика здесь такая-же, как и в режиме сниффера: первый байт — код, второй — данные.

Команды для i2c мастер-режима могут быть такие:
0x05 — Старт (Или повстарт)
0x02 — Стоп
0x07 — Записать байт. (Во втором байте — данные, которые нужно записать)
0x10 — Прочитать байт, передать ACK
0x11 — Прочитать байт, передать NACK

Коды отчётов:
0x05 — Передан start-condition
0x02 — Передан stop-condition
0x07 — Передали байт, нам ответили ACK
0x08 — Передали байт, в ответ — NACK
0x10 — Прочитали байт, сказали ACK
0x11 — Прочитали байт, сказали NACK

После того, как все команды будут выполнены и на их место будет записан отчёт, список отправляется обратно в компьютер. Когда весь список будет отправлен, устройство переходит в мастер режим. Можно опять загонять команду 0x34 и новый список, или перевести отладчик в другой режим.

1-Wire мастер.

Этот режим, практически, является частью i2c мастера. Точнее, есть просто «Мастер-режим», в котором устройство выполняет команды из списка. Мы можем загнать в этот список команды для работы с i2c или 1-Wire, логика работы, при этом, не меняется.
Для работы с 1-Wire есть 5 команд:
0x01 — Послать RESET импульс, и прочитать PRESENSE.
0x03 — Прочитать байт
0x06 — Передать байт
0x12 — Подключить дополнительное питание на линию Dq
0x13 — Отключить дополнительное питание.

После выполнения списка, отладчик может выдать вот такие коды:
0x01 — Передали RESET, поймали PRESENSE импульс.
0x04 — Передали RESET, но PRESENSE не было.
0x06 — Байт прочитан
0x09 — Байт передан
0x12 — Дополнительное питание подключено
0x13 — Дополнительное питание отключено

Если 1-Wire устройство работает от паразитного питания, то для выполнения некоторых операций ему понадобится дополнительная подпитка. Как раз для этих целей существуют команды 0x12 и 0x13. Первая подключает ножку Dq к питанию, а вторая — переводит в режим Hi-Z. Хотя, команда отключения питания почти не используется, т.к. оно отключается само, как только начнёт выполняться любая другая команда.

  • Свежие записи
    • Нужно ли менять пружины при замене амортизаторов
    • Скрипят амортизаторы на машине что делать
    • Из чего состоит стойка амортизатора передняя
    • Чем стянуть пружину амортизатора без стяжек
    • Для чего нужны амортизаторы в автомобиле

    📸 Видео

    MCP2515, контроллер CAN шины с интерфейсом SPIСкачать

    MCP2515, контроллер CAN шины с интерфейсом SPI

    Урок 9. Адреса модулей на шине I2C. Arduino (что такое I2C, адресация, как изменить адрес модуля)Скачать

    Урок 9. Адреса модулей на шине I2C. Arduino (что такое I2C, адресация, как изменить адрес модуля)

    Подключение нескольких устройств, датчиков по I2C (АйТуСи) шинеСкачать

    Подключение нескольких устройств, датчиков по I2C (АйТуСи) шине

    Урок 24. Узнаём адреса устройств на шине I2CСкачать

    Урок 24. Узнаём адреса устройств на шине I2C

    Логический анализатор шины i2cСкачать

    Логический анализатор шины i2c

    Что такое I2C ??? Подключаем GY-521 и Oled 96*16 к STM 32Скачать

    Что такое I2C ??? Подключаем GY-521 и Oled 96*16 к STM 32

    FLprog урок №2 шины данных Uart\I2C\ICSP\OneWireСкачать

    FLprog урок №2 шины данных Uart\\I2C\\ICSP\\OneWire

    Подключение нескольких устройств по шине i2cСкачать

    Подключение нескольких устройств по шине i2c

    Arduino I2C связь между контроллерамиСкачать

    Arduino I2C связь между контроллерами

    Шина I2C.Скачать

    Шина I2C.

    Урок 26.3 Соединяем две arduino по шине I2C #iarduinoСкачать

    Урок 26.3 Соединяем две arduino по шине I2C #iarduino

    I2C расширитель портов ввода-вывода PCF8574 и ArduinoСкачать

    I2C расширитель портов ввода-вывода PCF8574 и Arduino

    Лекция 308. Шина I2CСкачать

    Лекция 308.  Шина I2C

    Arduino I2C Scanner devices | Arduino TutorialСкачать

    Arduino I2C Scanner devices | Arduino Tutorial

    PortableProg PRO (продолжение): тестер опто-транзисторов, тестер диодов (резисторов), I2C Sniffer.Скачать

    PortableProg PRO (продолжение): тестер опто-транзисторов, тестер диодов (резисторов), I2C Sniffer.

    Arduino CAN Monitor (простейший монитор шины CAN)Скачать

    Arduino CAN Monitor (простейший монитор шины CAN)

    Проверка работоспособности шины I2CСкачать

    Проверка работоспособности шины I2C
Поделиться или сохранить к себе:
Технарь знаток