Когда вы освобождаете и восстанавливаете контроль над SDA вокруг подтверждения i2c?

У меня странное поведение с библиотекой Energia Wire, поэтому я решил, что попытаюсь сделать i2c самостоятельно.

Я пишу свою собственную (битовую) реализацию i2c и делаю ее довольно простой. На данный момент я просто хочу обнаружить конкретное устройство i2c. Вот мой основной алгоритм.

  1. Начните сообщение, изменив SDA с High на Low, в то время как SCL остается высоким.
  2. Отправьте 7-битный адрес по одному биту за раз, установив SDA в высокий или низкий уровень, в то время как SCL низкий, а затем изменив SCL на высокий, чтобы ведомое устройство считывало каждый бит.
  3. Отправить 1 бит записи или чтения.
  4. Получите подтверждение от ведомого устройства.
  5. Завершите сообщение, изменив SDA с низкого уровня на высокий, в то время как SCL остается высоким.

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

Итак, после того, как последний бит чтения/записи был установлен на SDA, а SCL установлен на HIGH, мне нужно знать, каков порядок операций, чтобы получить Ack от ведомого устройства.

Я перепробовал все возможные комбинации, но, похоже, они не работают должным образом. Казалось бы, что я должен сделать следующее:

setMode(SDA, INPUT);                //Release the SDA line to the slave device
digitalWrite(SCL,LOW);              //Pulse the SCL line
digitalWrite(SCL,HIGH);
int ack = digitalRead(SDA) == LOW;  //Read from the SDA line
setMode(SDA, OUTPUT);               //Seize control of the SDA line

Последовательность выше, похоже, не работает. Мой цифровой анализатор не распознает мои сообщения должным образом.

Любые исправления в моих предположениях или изменения в приведенном выше коде были бы очень полезны.

Для дальнейшего уточнения:

Я использую среду разработки под названием «Энергия». Это форк Arduino, который используется для «упрощения» процесса программирования процессоров TI MSP430x. Во всяком случае, похоже, что у него нет никакого понятия о режиме «OpenCollector».

Это либо Input, Output, либо Input_Pullup. Мне интересно, не является ли Input_Pullup их версией режима OpenCollector. Я попробую это. Здесь есть интересное обсуждение Input, Output, Input_Pullup:

Константы энергии

Вы не «отпускаете контроль над SDA». Оба контакта должны быть с открытым коллектором, что означает, что ваше устройство работает только на низком уровне. Вместо высокого уровня он просто становится высоким Z, позволяя подтягивающим резисторам тянуть линию к высокому уровню, если только другое устройство не переходит в низкий уровень (подчиненное устройство отправляет ACK). Похоже, вам нужно прочитать об I2C.
Если, случайно, вы не можете использовать открытый коллектор, альтернативой является установка состояния выхода вывода на низкий уровень, а затем переключение режимов вывода между выходом для 0 и входом для 1.
Что вы имеете в виду под "кажется, не работает"? Нужно показать осциллограмму.
Итак, я думаю, что digitalWrite(SDA, LOW); сообщает моему приложению, что я хочу, чтобы пин был низким, когда я его контролирую. pinMode (SDA, OUTPUT) — я беру на себя управление контактом (заставляя его опускаться), а pinMode (SDA, INPUT) — я освобождаю контроль над контактом (позволяя перейти на ВЫСОКИЙ уровень через подтягивающие резисторы)? Я попробую. Спасибо ДоксиЛовер!!! Поместите свое предложение в качестве ответа, и если оно сработает, я отмечу его как правильный ответ!

Ответы (2)

Большая часть ваших проблем, вероятно, будет связана с тем, что вы устанавливаете эти линии высоко, а не позволяете им плавать. SDA и SCL становятся высокими, потому что есть резистор, подтягивающий их до +V, а не потому, что они имеют высокий уровень. Многие люди не понимают, что тактовая линия также предназначена для работы таким образом.

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

  • настроить данные
  • поднять часы
  • подождите соответствующее битовое время
  • опустить часы

То, как вы это делаете, может привести к неприятностям следующим образом:

  • пишешь ПДД -- скажем, низкий.
  • вы поднимаете часы, так что SCL теперь высокий
  • вы выпускаете SDA, потому что хотите его прочитать.
  • SDA становится высоким, если нет ACK

Сюрприз! Вы только что создали условие СТОП, не осознавая этого.

Да, согласно моему цифровому анализатору, именно это и происходит... Я дохожу до бита ACK, а затем вижу, что происходит остановка и начало.
Если ни одно из ведомых устройств на шине I2C не использует растяжение тактовой частоты, на самом деле нет никаких недостатков в том, чтобы ведущее устройство активно управляло тактовой частотой в обоих направлениях. Конечно, если ведомые устройства действительно используют растяжение часов, ведущее устройство должно будет не только использовать пассивную подтяжку при освобождении часов, но и ждать, пока часы действительно перейдут в высокий уровень каждый раз, когда они освобождаются, и учитывать тот факт, что подчиненные устройства не работают . не требуется помещать действительные данные в SDA, пока они не собираются выпускать SCL.
Те, кто управляет SCL, склонны «учиться», что они всегда могут это сделать, особенно если они используют только EEPROM, датчики температуры и все, что не содержит микроконтроллера внутри. И вот однажды они узнают обратное! Итак, мне нравится напоминать людям, каков был первоначальный замысел.

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

Ваш код должен достаточно долго импульсировать SCL, чтобы у ведомого было достаточно времени для установки значения (не менее 4,7 мкс).

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

Очень хороший. Спасибо за этот совет/информацию.