Считывание регистров I2C в качестве подчиненного устройства

Мне нужно прочитать регистры сообщения, полученного от onReceive(). Я читал здесь, что

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

Поэтому я подумал, что, поскольку хосты устанавливают регистры, дважды вызывая функцию write (), я мог бы просто дважды выполнить функцию обработчика onReceive (), как это

byte CURRENT_REGISTER = 0x00;

void onMessage(int numBytes){
  if(CURRENT_REGISTER == 0x00 && numBytes == 1){
    CURRENT_REGISTER = Wire.read();
    return;
  }

  char msg[numBytes];
  for(int i = 0; i < numBytes; i++){
    msg[i] = Wire.read();
  }
  
  //логическая функция идет сюда

  CURRENT_REGISTER = 0x00;
}

Но потом я заметил здесь, что

Этот первый байт, записанный здесь "r", перемещает указатель регистра в регистр с адресом "r". Вы можете думать об указателе как о головке для чтения/записи.
Теперь, когда указатель "указывает" на конкретный регистр, который вы хотели, эта команда заменит байт, хранящийся в этом регистре, значением "v".

что заставило меня подумать, что после endTransmission ()он отправил только одно сообщение, которое разрушило бы эту идею. Так ли это, и если да, то как я могу получить регистры в качестве подчиненного?

, 👍2

Обсуждение

Вы действительно должны предоставить больше контекста. Чего вы пытаетесь достичь? О каких регистрах ты говоришь?, @chrisl

@chrisl я пытался привести минимальный пример, так как контекст очень большой. Но если вы хотите знать, я пытаюсь заменить wiimotion+ IMU на BNO055, и мне нужно связаться с wimmote по соединению I2C в определенном формате, чтобы быть понятым. Существуют определенные регистры, которые wiimote ожидает, что при записи он получит определенный ответ, и я пытаюсь эмулировать эти ответы с помощью arduino nano. Мне нужно знать регистр, чтобы знать, как реагировать. Если вам нужно больше контекста, посмотрите на эту ссылку wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus, @TryingMyBest

Угрозы форума, на которые вы ссылаетесь, совершенно не связаны с wiimote. Единственное общее заключается в том, что - как и многие другие устройства - wiimote, похоже, читает свои периферийные устройства, сначала отправляя "адрес регистра" в периферийное устройство (адрес внутренней памяти датчика), который он затем хочет прочитать или записать. Из того, что вы связали в комментариях, для wiimote этот "адрес регистрации" на самом деле не соответствует регистру. Это больше похоже на команду, которую посылает мастер., @chrisl

Поэтому вам нужно сначала действительно понять протокол связи, который использует wiimote. Тогда вы сможете приступить к его реализации. Из вашей ссылки видно, что сначала происходит процесс инициализации. Также что-то о возможном шифровании. Этот сайт нелегко понять., @chrisl

@chrisl итак, wiimote взаимодействует через i2c. эти регистры на самом деле имеют значение, и wiimotion plus не зашифрован, но даже если бы это было так, я инициализирую его таким образом, что шифрование не имеет значения. Это не только неверно, [но это даже было сделано раньше](https://forum.arduino.cc/index.php?topic=8507.0) наоборот, с arduino nano в качестве ведущего и wiimotion+ в качестве ведомого., @TryingMyBest

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

@chrisl Игры, которые используют wii motion plus, зависят от конкретных команд или регистров, как бы вы их ни называли, чтобы реагировать соответствующим образом, иначе игра выйдет из строя. Я знаю, каковы будут ответы, но я не знаю, как определить, о каком регистре/команде спрашивают. Вот почему я спрашиваю: "как читать регистры I2C как подчиненное устройство"., @TryingMyBest

Ведомый I2C никогда не читает никаких регистров, только ведущий может инициировать транзакции шины. Ведомое устройство может быть только записано, и оно не имеет никакого контроля над тем, что оно получает. Я считаю, что у вас есть некоторое недоразумение относительно I2C, из-за которого трудно понять, о чем вы спрашиваете., @Sim Son


1 ответ


1

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

С I2C и типичным протоколом связи регистра у вас есть 3 способа связи:

  • Мастер хочет написать:
    • Мастер выполняет передачу, при этом первый байт является адресом регистра, а следующие байты являются данными, которые должны быть записаны в адресный регистр (и следующие регистры).
  • Мастер хочет почитать:
    • Мастер выполняет передачу 1 байта с адресом регистра, то есть хочет прочитать
    • Ведущий запускает запрос на 1 или более байтов, и ведомый отправит ранее запрошенный регистр (и последующие регистры, пока больше байтов не будет доступно или запрошено).
  • Некоторые устройства имеют последовательное считывание. Для этих устройств адрес регистра не сбрасывается при выполнении операции. Таким образом, мастер мог выполнять больше запросов и считывать больше данных из регистров. Здесь текущий адрес регистра увеличивается при каждом чтении.

Это означает, что основной цикл записи имеет только 1 передачу (только 1 конечная передача() в основном коде), поскольку каждый первый байт в основной передаче отправки обрабатывается как адрес регистра. Ваш фрагмент кода этого не позволяет. Чтобы решить эту проблему, просто удалите проверку numBytes и оператор return.


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

Протокол I2C: Это общий протокол связи, который Wiimote использует для своих периферийных устройств. Он использует 2 линии и структуру "ведущий-ведомый". Это означает, что любая связь контролируется ведущим устройством (в данном случае Wiimote), а подчиненное устройство (периферийное, например, Motion+, Nunchuk или ваш Arduino) ничего не может сделать само по себе. Протокол I2C имеет маркеры для начала и окончания сообщения и может адресовать каждому ведомому устройству на шине свой конкретный адрес (который отправляется перед данными). Протокол НЕ содержит никаких правил о содержании каждого сообщения. Поэтому при написании кода с помощью библиотеки Wire (библиотеки ардуино для взаимодействия с оборудованием I2C) вы получаете только буфер, полный байтов данных. Вы сами должны интерпретировать эти байты так, как это необходимо для вашего приложения.

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

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

Пример: Давайте представим себе простой датчик расстояния. Он имеет 2 байта/регистра внутренней памяти. Первый байт/регистр предназначен для настройки датчика; второй байт/регистр представляет измеренное расстояние. Общим протоколом связи для такого чипа может быть:

Мастер отправляет адрес регистра, к которому он хочет получить доступ
, если Мастер хочет записать в регистр
    Ведущий отправляет байты ведомому устройству
    Ведомый сохраняет байты в ранее выбранный регистр (и следующие регистры)
, если ведущий хочет прочитать из регистра
    Ведущий запрашивает X байт от ведомого устройства
    Ведомое устройство отправляет X байтов с содержимым ранее выбранного регистра (и следующих регистров)

Мастер I2C теперь хочет настроить датчик (например, установить частоту измерения), записав, таким образом, соответствующий байт в первый байт/регистр. Сначала он отправит адрес регистра конфигурации ведомому устройству, который равен 0 (первый байт/регистр). Затем он отправит еще один байт, который является новым значением регистра конфигурации.

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

Таким образом, для ведомого устройства первый байт основной передачи отправки должен обрабатываться как адрес регистра. Более сложные подчиненные классы могут иметь адрес регистра 16 бит (2 байта) или даже больше.


Теперь перейдем к вашей проблеме, имитирующей движение Wii+. Описание на сайте, на которое вы ссылаетесь, довольно сложное. К сожалению, я ничем не могу вам в этом помочь. Но вы можете попробовать использовать уже существующую библиотеку, которая имитирует периферийное устройство Wiimote: Arduino-Wiimote

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

При более тщательном поиске (для комбинаций терминов, таких как "github wiimote arduino"), вы можете найти больше библиотек для этого. Я потратил лишь ограниченное количество времени.

,