Связь MCU с MCU I2C

У меня есть 2 MCU, и я хочу соединить их вместе по шине I2C. MCU1 будет контроллером, а MCU2 будет целью. Только эти 2 MCU находятся на шине. Эта конфигурация фиксирована, и я не могу ее изменить.

Есть 2 сценария. В первом сценарии к шине подключены только MCU1 и MCU2, а во втором сценарии к этой общей шине также подключены некоторые дополнительные устройства I2C.

Моя основная цель подключить их, как указано выше, — отправить данные с MCU2 (цель) на MCU1 (контроллер).

Насколько я понимаю I2C, это протокол команд-ответов. Контроллер дает команды таргетам, а затем таргеты отвечают на эту команду и отправляют свои данные в контроллер. Цели не могут отправлять свои данные самостоятельно, не получив предварительно команду.

Если контроллер хочет получить 32 байта данных от цели, то какую команду он отправит цели, и как цель будет утверждать, что она получила действительную команду для отправки данных? Я думаю, что это называется передачей данных в «блочном режиме».

Мой целевой адрес зафиксирован как 0x08.

Если вы хотите установить связь между MCU2 и MCU1, MCU2 должен быть в ведущем режиме, а MCU1 — в ведомом. В вашем случае вы должны перевести MCU1 и MCU2 в ведомый режим. Когда MCU1 или MCU2 должны обмениваться данными по шине, его статус должен быть изменен на MASTER, а затем он запрашивает шину.
Это немного сбивает с толку выше об изменении режима для MCU2. Зачем мне менять режимы? Могу ли я сделать передачу данных с фиксированными режимами для MCU1 и MCU2?

Ответы (1)

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

Проще всего было бы поменяться ролями ведущего и ведомого, чтобы именно ведущее устройство инициировало отправку данных ведомому устройству.

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

Требуемые конкретные вызовы API I2C зависят от того, какое устройство и HAL вы используете. На физическом уровне это будет «чтение I2C», инициированное мастером, когда мастер считывает 32 байта после отправки адреса ведомого.

Функция библиотеки, которую я использую, имеет возможность выбрать адрес I2C как 7-битный или 10-битный. Как я должен решить об этом?
На самом деле не имеет значения, если вы используете одинаковые настройки с обеих сторон. Поскольку вам не нужен 10-битный, я предлагаю 7-битный.
Это означает, что 7-битный адрес означает, что 7 бит для адреса и дополнительные 3 бита для битов S, R/W, ACK. Точно так же 10-битный адрес означает 10 бит для адреса и дополнительные 3 бита, как указано выше, И не как 7 + 3 бита = 10 бит?
В «блочном режиме» передачи данных, если я установлю размер блока как 1 байт или 2 байта, будет ли он таким же, как «один байтовый режим» или «одиночный режим слова»?
Да. Я не думаю, что используется термин «режим одного слова». I2C работает на уровне байтов. Ваш мастер может запросить ведомое устройство с помощью одного байта, чтобы проверить, доступны ли данные, но будет сложнее заставить работать две разные длины передачи. I2C может быть достаточно сложным для отладки.
Если на моем I2C Master (MCU1) установлен Linux, и я использую утилиты i2cset() linux.die.net/man/8/i2cset и i2cget() linux.die.net/man/8/i2cget для связи и получить данные от подчиненного устройства i2C (MCU2), то что будет означать параметр «адрес данных» в вышеуказанных утилитах? Я могу понять, что «chip-address» — это адрес моего ведомого устройства = 0x08, но какой следующий параметр будет в моем случае, когда ведомое устройство — это микроконтроллер, а не сенсорный чип? Как правило, в случае сенсорных чипов этот вышеуказанный параметр является адресом целевого регистра, из которого будут считываться данные.
Обычно используется концепция «регистров» поверх базового I2C, где один байт используется в качестве адреса среди диапазона настраиваемых слотов значений (из-за отсутствия лучшего слова) в адресуемом ведомом устройстве. Не все чипы используют регистры, и вы действительно не можете использовать это, поскольку вы сообщаете только один 32-байтовый параметр. Чтобы использовать регистры, вам нужно будет реализовать это в ведомом устройстве. Linux i2cset работает только с регистрами. i2cget может не использовать регистры, если они не указаны — я не знаю.