Главная chevron_right Функции chevron_right Связь chevron_right Wire.onReceive()

Wire.onReceive()

Wire.onReceive() регистрирует функцию обратного вызова, которая автоматически вызывается, когда I²C-контроллер отправляет данные на адрес вашего устройства.

Полная статья

Описание

onReceive() регистрирует функцию обратного вызова для работы в режиме периферийного устройства на шине I²C. Когда контроллер отправляет данные на адрес вашего устройства, библиотека автоматически вызывает зарегистрированную функцию и передаёт ей количество принятых байтов. Внутри этой функции можно считать данные с помощью Wire.read().

Эта функция является частью библиотеки Wire.

Синтаксис

Wire.onReceive(handler)

Параметры

  • handler: функция обратного вызова, которая вызывается при получении данных. Она должна иметь следующую сигнатуру:
  • Параметр: int numBytes — количество байт, полученных от устройства-контроллера.
  • Возврат: void — ничего не возвращает.

Возвращает

Ничего.

Пример кода

void setup() {
  Wire.begin(0x08);             // Подключиться к шине I2C как периферийное устройство с адресом 0x08
  Wire.onReceive(receiveEvent); // Зарегистрировать функцию обратного вызова
}

void receiveEvent(int numBytes) {
  while (Wire.available()) {
    char c = Wire.read();
    // Обработать полученный байт
  }
}

Где применяется

  • Периферийный микроконтроллер — один Arduino принимает команды или данные от другого Arduino, выступающего контроллером.
  • Расширитель периферии — плата на базе Arduino работает как I²C-устройство и получает настройки или задания от основного контроллера.
  • Пользовательский I²C-датчик — вы реализуете собственный протокол поверх I²C и обрабатываете входящие пакеты в обратном вызове.
  • Многоузловые системы — несколько ведомых устройств на одной шине, каждое реагирует на свой адрес.

Практические замечания

  • Функцию onReceive() нужно вызывать после Wire.begin(address), где address — адрес вашего ведомого устройства.
  • Обратный вызов выполняется в контексте прерывания, поэтому внутри него нельзя использовать delay(), Serial.print() и другие функции, которые сами зависят от прерываний. Данные лучше сохранять в буфер, а обрабатывать в loop().
  • Параметр int numBytes сообщает, сколько байт доступно для чтения. Не обязательно считывать ровно столько — Wire.available() позволяет проверить остаток в любой момент.
  • Если не вычитать все байты из буфера внутри обратного вызова, следующий вызов может получить «хвост» предыдущей передачи. Читайте буфер полностью.
  • Для отладки логики обратного вызова удобно выставлять флаг volatile bool received = true внутри него и уже в loop() печатать данные через Serial.