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.