Вызов I2C во время Wire.requestFrom
Какая команда I2C выполняется во время Wire.requestFrom(address, quantity)
?
Правильно ли, что Wire ставит условие Start, затем 7-битный адрес добавляется с битом чтения? Чем это будет отличаться от Wire.write(address)?
@Dzung Nguyen, 👍0
2 ответа
Лучший ответ:
В библиотеке Wire
нет Wire.write(address)
. Функция write()
берет данные и помещает их во внутренний буфер записи библиотеки. Она ничего не делает на шине I2C.
Для операции записи на главном устройстве (отправка от главного устройства к подчиненному) необходимы следующие команды:
Wire.beginTransmission(address);
Wire.write(data);
Wire.endTransmission();
Только последняя из этих команд что-то делает на шине I2C. Она генерирует условие Start, отправляет байт, состоящий из адреса (который мы установили в операторе beginTransmission()
) и бита направления, который здесь всегда равен 0
, поскольку эти команды предназначены для операции записи главного устройства. Затем она отправляет данные и завершает передачу условием остановки. Вы не можете контролировать, какое значение имеет бит направления. Параметр beginTransmission()
должен быть длиной только 7 бит. Если вы укажете больший адрес, функция просто отрежет старший бит и в любом случае выполнит операцию записи.
Для операции чтения ведущего устройства действие на шине I2C происходит внутри функции requestFrom()
. Она отправляет условие Start, за которым следует адрес и бит направления, установленный в 1
(здесь вы снова не можете контролировать значение бита направления). Затем она считывает байты, поступающие от ведомого устройства, пока все запрошенные байты не будут получены. Затем вы можете считывать байты из внутреннего буфера библиотеки с помощью функции Wire.read()
. Опять же, эта функция ничего не делает на шине I2C. Она взаимодействует только с буфером библиотеки.
Когда вы отправляете адрес с помощью write(), это адрес регистра на устройстве, а не адрес устройства на шине.
Адрес устройства задается с помощью beginTransmition() и requestFrom().
Если устройство требует установки регистра перед requestFrom(), адрес регистра следует отправить с помощью write(), обернутого в beginTransmition() и endTransmition().
Пример:
Wire.beginTransmission(I2C_ADC121);
Wire.write(REG_ADDR_RESULT); // отправляем регистр на чтение, регистр 'result'
Wire.endTransmission();
Wire.requestFrom(I2C_ADC121, 2);
byte buff[2];
Wire.readBytes(buff, 2); // считываем значение регистра 'result'
- Отправка и получение различных типов данных через I2C в Arduino
- Как выбрать альтернативные контакты I2C на ESP32?
- Альтернативы библиотеке Wire для I2C
- Библиотека Wire.h работает на Uno, но не компилируется для ATtiny85
- I2C связь между Arduino Uno и Nodemcu32-s (ESP32)
- Как обнаружить ошибки I2C с помощью requestFrom()
- Проблемы с I2C и Wire.Available()
- Считывание значений с емкостного сенсорного датчика TTP229 на arduino
Когда мастер считывает данные, вы говорите, что ведомый может закончить передачу с помощью nack. Проверьте протокол i2c, пожалуйста., @Jot
@Jot Ммм, похоже, ты прав. Это не указано в протоколе. Но я не понимаю, что происходит, когда у ведомого устройства недостаточно байт для отправки. Все оставшиеся байты считываются как
0xFF
, поскольку ведомое устройство больше не переводит линию SDA в низкий уровень?, @chrislДа, именно это и произойдет. Мастер не получает меньше байтов, но и не больше, чем запрошено. Пока на шине нет ошибок, мастер получает столько байтов, сколько хочет, независимо от того, сколько байтов пытается отправить слейв., @Jot