Wire.write()
Wire.write() помещает байты в I²C-буфер контроллера (данные уйдут при Wire.endTransmission()) или формирует ответ периферии внутри Wire.onRequest().
Полная статья
Описание
Wire.write() — основной инструмент для передачи данных по шине I²C, и его поведение зависит от того, в какой роли работает плата.
Когда плата выступает контроллером, Wire.write() не отправляет данные немедленно — она накапливает байты в буфере, который открывается вызовом Wire.beginTransmission(address). Реальная передача по шине происходит только при вызове Wire.endTransmission(). Это означает, что между Wire.beginTransmission(address) и Wire.endTransmission() можно вызвать Wire.endTransmission() несколько раз, чтобы последовательно сложить в буфер адрес регистра, команду и данные.
Когда плата работает как периферийное устройство, Wire.write() вызывают внутри обработчика Wire.onRequest(): именно здесь устройство готовит байты, которые контроллер считает при следующем запросе.
Функция является частью библиотеки Wire.
Синтаксис
Wire.write(value)Wire.write(string)Wire.write(data, length)
Параметры
value— один байт для отправки. Допустимый тип данных:byte.string— строка в стиле C, передаётся как последовательность байтов. Допустимый тип данных:char*.data— массив байтов для передачи. Допустимый тип данных:byte[].length— сколько байтов из массиваdataнужно отправить. Допустимый тип данных:size_t.
Возвращает
Количество байтов, фактически принятых в буфер (в режиме контроллера) или отправленных в ответ (в режиме периферии). В большинстве случаев это значение не нужно проверять, но при отладке оно покажет, не переполнился ли буфер: если вернулось меньше, чем вы передали, часть данных потеряна.
Тип данных: size_t.
Пример кода
В примере контроллер отправляет один байт устройству с адресом 0x2C:
byte value = 0;
void setup() {
Wire.begin();
}
void loop() {
Wire.beginTransmission(0x2C);
Wire.write(value);
byte result = Wire.endTransmission();
value++;
if (value == 64) {
value = 0;
}
delay(500);
}
Пример ответа периферийного устройства на запрос контроллера:
void setup() {
Wire.begin(0x08);
Wire.onRequest(requestEvent);
}
void requestEvent() {
Wire.write("OK");
}
void loop() {
}
Где применяется
- Запись в регистры I²C-устройств — сначала отправляется адрес регистра, затем одно или несколько значений одной транзакцией.
- Передача команд датчику или модулю — контроллер формирует пакет через
Wire.write()и завершает его черезWire.endTransmission(). - Ответ периферийного устройства — внутри
Wire.onRequest()устройство возвращает байты контроллеру по запросу. - Передача бинарных данных фиксированной длины — удобно использовать вариант с массивом
dataиlength, чтобы отправить структуру целиком.
Практические замечания
- В режиме контроллера
Wire.write()не отправляет данные сразу. Байты накапливаются в буфере; отправка по шине происходит только при вызовеWire.endTransmission(). - В режиме периферии вызывайте
Wire.write()внутриonRequest(). Именно эти байты контроллер и получит в ответ на свой запрос. - Следите за размером буфера. Если суммарный объём данных превысит внутренний буфер
Wire, лишние байты будут молча отброшены — возвращаемое значение поможет это обнаружить. - Строки отправляются побайтово, без терминатора.
Wire.write("OK")передаст символыOиK, но нулевой байт'\0'в конце как'\0'не добавляется автоматически. - Проверяйте результат
Wire.endTransmission(). Даже еслиWire.write()успешно приняла байты в буфер, устройство на шине может не подтвердить свой адрес или данные — об этом сообщит код ошибкиendTransmission().
Примечания и предупреждения
Не путайте Wire.write() с Serial.print(): Wire.write() передаёт сырые байты, а не текстовое представление числа. Например, Wire.write(65) отправит байт со значением 65 (символ 'A'), тогда как Serial.print(65) вывела бы строку "65". Если нужно передать число в виде текста, сначала преобразуйте его в строку и используйте вариант с char*, либо отправляйте ASCII-символы по одному.