Операция чтения I2C в TCA9539

i2c

Я использую устройство TI TCA9539 (http://www.ti.com/lit/ds/symlink/tca9539.pdf) с контактами A1 и A0, подключенными к земле, в результате чего адрес записи становится 0x74.

Изображение байта адреса

У меня нет проблем с записью по этому адресу устройства и выполнением необходимых функций, однако при попытке чтения регистров с помощью функций чтения Arduino я получаю NACK. 0x75 — правильный ли адрес чтения?

По второму вопросу:

На основе спецификации устройства для операции чтения:

Чтение с подчинённого устройства очень похоже на запись, но требует некоторых дополнительных действий. Чтобы прочитать данные с подчинённого устройства, Ведущее устройство должно сначала указать ведомому, из какого регистра оно хочет выполнить чтение. Это делается ведущим устройством, которое запускается отключить передачу аналогично записи, отправив адрес с битом R/W, равным 0 (означает запись), а затем адрес регистра, из которого он хочет прочитать. Когда ведомое устройство подтверждает это, регистр адреса, ведущее устройство снова отправляет условие СТАРТ, а затем адрес ведомого устройства с установленным битом R/W на 1 (что означает чтение). На этот раз ведомое устройство подтверждает запрос на чтение, а ведущее устройство освобождает SDA. шину, но продолжает подавать тактовый сигнал ведомому устройству. В этой части транзакции ведущее устройство становится главный-приемник, а подчиненный становится подчиненным-передатчиком. Ведущее устройство продолжает посылать тактовые импульсы, но освобождает линию SDA, чтобы ведомое устройство могло передавать данные. В конце каждого байта данных ведущее устройство отправляет ACK ведомому устройству, давая ему знать, что оно готово к больше данных. Когда ведущее устройство получает ожидаемое количество байтов, оно отправляет NACK, сигнализируя Ведомое устройство прекращает обмен данными и освобождает шину. Ведущее устройство выполняет команду STOP.

Вот код, который я пытаюсь использовать,

Wire.begin();
Wire.beginTransmission(0x74); // начать передачу i2c как запись адреса
Wire.write(0x01)              // регистр, из которого нужно прочитать
Wire.beginTransmission(0x75); // начать передачу по I2C, как указано в адресе чтения

Я считаю, что чтение по I2C и функции библиотеки Arduino для чтения мне не понятны. Кто-нибудь использовал это устройство для чтения?

, 👍0


2 ответа


Лучший ответ:

0

Вы неправильно поняли, как работает библиотека Wire. Она сама всё делает с битом направления.

Операция записи:

  • Wire.beginTransmission() принимает в качестве параметра 7-битный адрес. Бит направления автоматически и внутренне устанавливается на операцию записи.
  • Wire.write() записывает значение во внутренний буфер библиотеки, но не выполняет никаких действий на фактической шине I2C
  • Наконец, вы вызываете функцию Wire.endTransmission() для окончательной записи на шину I2C. До вызова этой функции библиотека не выполняет никаких действий на шине. Поэтому вам необходимо вызвать её, чтобы данные достигли ведомого устройства.

Операция чтения:

  • Для чтения с ведомого устройства предусмотрена дополнительная функция: Wire.requestFrom(). Она принимает в качестве параметров (7-битный) адрес и количество запрошенных байтов и возвращает количество байтов, фактически считанных с ведомого устройства (это важно, если ведомое устройство отправляет меньше данных, чем запрошено). После вызова этой функции считанные байты теперь находятся во внутреннем буфере библиотеки.
  • Чтобы получить полученные байты из внутреннего буфера библиотеки, необходимо использовать функцию Wire.read(). Опять же, она не выполняет никаких действий на шине I2C. Она просто считывает данные из внутреннего буфера.

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

Посмотрите на эти изображения со страниц 23 и 24 технического описания:

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

Операция записи:

Wire.begin();
Wire.beginTransmission(slave_address);
Wire.write(register_address);
Wire.write(new_register_data);
Wire.endTransmission();

Адрес регистра указан в техническом описании. В данном случае это регистр с адресом 0x01 (хотя это бессмысленно, поскольку этот регистр доступен только для чтения).

Операция чтения

Wire.begin();
Wire.beginTransmission(slave_address);
Wire.write(register_address);
Wire.endTransmission();
if(Wire.requestFrom(slave_address,1) > 0 ){
    byte data = Wire.read();
}

Здесь мы сначала выполняем операцию записи, чтобы сообщить ведомому устройству, к какому регистру мы хотим получить доступ. Затем мы запрашиваем данные из этого регистра с помощью функции Wire.requestFrom(). Передача данных из внутреннего буфера в нашу программу выполняется с помощью функции Wire.read() (но только в том случае, если данные действительно были получены).


Для адреса ведомого устройства: это зависит от того, как настроены выводы A0 и A1. Таблицу с соответствующими адресами можно найти на странице 21 технического описания. Обратите внимание, что бит направления данных в них НЕ учитывается. При использовании библиотеки Wire об этом можно не беспокоиться.

,

Если это решило вашу проблему, пожалуйста, отметьте ответ как правильный, чтобы другие могли его сразу увидеть. Спасибо., @chrisl

Готово, ответы приняты!, @JYasir


1

Библиотеки Arduino I2C ожидают 7-битный адрес подчиненного устройства, а не 8-битный адрес + бит чтения/записи, и будут управлять битом чтения/записи внутренне в зависимости от того, выполняете ли вы запись или чтение.

Итак, начинаем передачу 0x74

Записать 0x01

Конец передачи

Начать передачу 0x74

Читать n

Конец передачи

,

Перед началом чтения необходимо завершить первую передачу. Фактическое действие I2C выполняется при вызове endTransmission()., @chrisl