Общие сведения:
Шина I2C (ай-ту-си) это аббревиатура от "Inter-Integrated Circuit" - шина передачи данных между интегральными схемами. Данная шина изобретена компанией Philips Semiconductor (теперь NXP), для передачи данных между чипами на одной плате по двум линиям. Но простота протокола и удобство подключения привели к тому, что в настоящее время данная шина широко применяется для подключения отдельных модулей к микроконтроллерам.
Для возможности подключения нескольких ведомых к одной шине используются адресация. Каждое ведомое устройство на шине I2C имеет свой уникальный адрес. Только мастер является инициатором приёма/передачи данных, он отправляет сигнал Start за которым следует адрес ведомого и бит направления передачи. Завершается пакет, так же по инициативе мастера, который отправляет сигнал Stop. С более подробным описанием сигналов на шине I2C, составе пакета, подтягивающих резисторах, паразитных ёмкостях и длине шины I2C, можно ознакомиться на странице Wiki - I²C - Inter-Integrated Circuit, краткое руководство.
Аппаратная шина I2C это шина реализованная на физическом уровне (внутренними блоками микроконтроллера), такая шина имеет заранее определённые выводы. На платах Arduino UNO и Piranha UNO есть только одна аппаратная шина I2C использующая выводы: A4 - SDA и A5 - SCL. На некоторых платах, например, Arduino UNO R4 есть сразу несколько аппаратных шин I2C. Но есть и платы с микроконтроллерами у которых вообще нет аппаратных шин I2C. Достоинство аппаратных шин в том, что они не используют вычислительные ресурсы микроконтроллера, он может заниматься выполнением вашей программы параллельно с тем как принимаются или передаются данные по шине, "отвлекаясь" только на прерывания окончания приёма/передачи или совпадение адреса ведомого.
Для работы с аппаратной шиной в Arduino IDE используется предустановленная библиотека Wire.h у которой заранее определены имена объектов:
- Wire- для работы с основной (или единственной) аппаратной шиной I2C.
- Wire1- для работы с первой (после основной) аппаратной шиной I2C.
- Wire2- для работы с второй аппаратной шиной I2C и т.д.
Программная шина I2C это шина реализованная (как понятно из названия) программно. Такая шина имеет ряд недостатков: она занимает память программ и часть ОЗУ, она использует вычислительные ресурсы микроконтроллера. Но у такой шины есть два преимущества:
- Можно создать несколько шин I2C, даже если их не было у микроконтроллера.
 Например, на плате Arduino UNO можно создать до 10 программных шин I2C.
- Можно выбрать любые выводы для создания шины I2C.
 Выводы должны поддерживать работу как логический вход/выход.
Для реализации программных шин I2C предлагаем воспользоваться разработанной нами библиотекой iarduino_I2C_Software.h. Эта библиотека имеет тот же синтаксис, что и библиотека Wire.h и поддерживает все её методы и функции для работы в качестве мастера. Обе библиотеки могут работать в одном скетче, так объекты библиотек создаются как экземпляры разных классов:
- Объекты библиотеки Wire являются экземплярами класса TwoWire.
- Объекты библиотеки iarduino_I2C_Software являются экземплярами класса SoftTwoWire.
Подключение:
Шина I2C состоит из двух диний:
- SDA "serial data" - последовательные данные
- SCL "serial clock" - последовательное тактирование.
Для аппаратной шины I2C выводы линий SDA и SCL указаны на плате или в документации.

Для программной шины I2C выводы SDA и SCL вы назначаете сами.

Примеры:
В данном разделе раскрыты примеры работы в качестве мастера по программной шине I2C с использованием библиотеки iarduino_I2C_Software. Сама библиотека содержит больше примеров, доступных из меню Arduino IDE: Файл / Примеры / iarduino_I2C_Software.
Во всех примерах программная шина I2C создаётся на выводах: 3 (SDA) и 4 (SCL).
ВАЖНО: Будьте осторожны с примерами записи данных в регистры ведомого! Некоторые модули, в т.ч. Flash-I2C и Metro, могут сохранять записанные данные регистров в энергонезависимую память.
Пример записи одного байта в один регистр:
В примере, ведомому с адресом adr, в регистр reg, записываться значение data, которое увеличивается на 1 каждую секунду.
// Данные для записи (можно менять): //
uint8_t adr  = 0x09;                 // Адрес ведомого на шине I2C.
uint8_t reg  = 50;                   // Номер регистра в который нужно записать значение.
uint8_t data = 0;                    // Значение для записи в регистр.
                                     //
#include <iarduino_I2C_Software.h>   // Подключаем библиотеку для работы с программной шиной I2C.
SoftTwoWire sWire(3,4);              // Создаём объект, указав выводы: SDA, SCL.
                                     // Допускается создавать несколько объектов, следовательно, несколько программных шин I2C.
void setup(){                        //
     sWire.begin();                  // Инициируем работу с программной шиной I2C.
}                                    //
                                     //
void loop(){                         //
     sWire.beginTransmission(adr);   // Инициируем передачу данных по шине I2C к устройству с адресом adr. При этом сама передача не начнётся.
     sWire.write(reg);               // Помещаем в буфер для передачи один байт: адрес регистра для записи.
     sWire.write(data);              // Помещаем в буфер для передачи один байт: данные для записи в регистр.
//   sWire.write(байт);              // Следующие данные помещённые в буфер, будут записаны в следующие по порядку регистры.
     sWire.endTransmission();        // Выполняем инициированную ранее передачу данных.
//   Задержка перед новой записью:   //
     data++;                         // Увеличиваем значение data.
     delay(1000);                    // Ждём 1 секунду.
}                                    //
Функция endTransmission() возвращает результат записи, который можно использовать для проверки: 0-успех, 1 - переполнен буфер, 2 - получен NACK при передаче адреса, 3 - получен NACK при передаче данных, 4 - другая ошибка, 5 - timeout.
Если вместо библиотеки iarduino_I2C_Software подключить библиотеку Wire, не создавать объект sWire, а использовать объект Wire, то тот же пример будет работать с аппаратной шиной I2C.
Пример записи нескольких байт:
В примере, данные для передачи (4 байта из массива arr) передаются ведомому с адресом adr, начиная с регистра reg. Запись выполняется каждую секунду.
// Данные для записи (можно менять): //
uint8_t adr   = 0x09;                // Адрес ведомого на шине I2C.
uint8_t reg   = 50;                  // Номер регистра с которого требуется начать запись.
uint8_t arr[] = {1,2,3,4};           // От 1 до 32 байт для записи в регистры.
uint8_t sum   = 4;                   // Количество байт для записи в регистры.
                                     //
#include <iarduino_I2C_Software.h>   // Подключаем библиотеку для работы с программной шиной I2C.
SoftTwoWire sWire(3,4);              // Создаём объект, указав выводы: SDA, SCL.
                                     // Допускается создавать несколько объектов, следовательно, несколько программных шин I2C.
void setup(){                        //
     sWire.begin();                  // Инициируем работу с программной шиной I2C.
}                                    //
                                     //
void loop(){                         //
     sWire.beginTransmission(adr);   // Инициируем передачу данных по шине I2C к устройству с адресом adr. При этом сама передача не начнётся.
     sWire.write(reg);               // Помещаем в буфер для передачи один байт (адрес первого регистра для записи).
     sWire.write(arr, sum);          // Помещаем в буфер для передачи sum байт данных из массива arr (данные для записи).
     sWire.endTransmission();        // Выполняем инициированную ранее передачу данных.
//   Задержка перед новой записью:   //
     delay(1000);                    // Ждём 1 секунду.
}                                    //
Функция endTransmission() возвращает результат записи, который можно использовать для проверки: 0-успех, 1 - переполнен буфер, 2 - получен NACK при передаче адреса, 3 - получен NACK при передаче данных, 4 - другая ошибка, 5 - timeout.
Если вместо библиотеки iarduino_I2C_Software подключить библиотеку Wire, не создавать объект sWire, а использовать объект Wire, то тот же пример будет работать с аппаратной шиной I2C.
Пример чтения одного или нескольких регистров:
В примере, читаются sum байт, начиная с регистра reg, ведомого с адресом adr.
// Данные для чтения (можно менять): //
uint8_t adr   = 0x09;                // Адрес ведомого на шине I2C.
uint8_t reg   = 50;                  // Номер регистра с которого требуется начать чтение.
uint8_t sum   = 4;                   // Количество байт для чтения из регистров.
                                     //
#include <iarduino_I2C_Software.h>   // Подключаем библиотеку для работы с программной шиной I2C.
SoftTwoWire sWire(3,4);              // Создаём объект, указав выводы: SDA, SCL.
                                     // Допускается создавать несколько объектов, следовательно, несколько программных шин I2C.
void setup(){                        //
     sWire.begin();                  // Инициируем работу с программной шиной I2C.
     Serial.begin(9600);             // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бит/сек.
}                                    //
                                     //
void loop(){                         //
     sWire.beginTransmission(adr);   // Инициируем передачу данных по шине I2C к устройству с адресом adr. При этом сама передача не начнётся.
     sWire.write(reg);               // Помещаем в буфер для передачи один байт (адрес первого читаемого регистра).
     sWire.endTransmission(false);   // Выполняем инициированную ранее передачу данных, без установки STOP.
     sWire.requestFrom(adr, sum);    // Читаем (запрашиваем) sum байт данных от устройства с адресом adr.
//   Выводим прочитанные данные:     //
     while( sWire.available() ){     // Если в буфере остались данные...
       Serial.println(sWire.read()); // Выводим очередной прочитанный байт.
     } Serial.println("----------"); //
//   Задержка перед новым чтением:   //
     delay(1000);                    // Ждём 1 секунду.
}                                    //
Функция requestFrom() возвращает количество прочитанных байт, а функция available() возвращает количество байт в буфере которые доступны для получения функцией read().
Если вместо библиотеки iarduino_I2C_Software подключить библиотеку Wire, не создавать объект sWire, а использовать объект Wire, то тот же пример будет работать с аппаратной шиной I2C.
Примеры использования объектов работы с шиной I2C:
Для работы библиотек iarduino с датчиками и модулями по шине I2C, нужно сначала подключить библиотеку для работы с самой шиной I2C, а потом указать ссылку на объект работы с шиной I2C в качестве первого параметра функции begin(). Таким образом библиотеки iarduino будут работать с модулями по той шине, с которой работает указанный им объект.
Для аппаратной шины указываются ссылки на объекты Wire, Wire1, Wire2, ..., библиотеки Wire.h, а для программной шины, ссылка на объект библиотеки iarduino_I2C_Software. Если ссылка не указана, то по умолчанию используется объект Wire (основная аппаратная шина I2C).
- Аппаратная шина:
В примере библиотека iarduino_AM2320 для работы с датчиком AM2320 будет работать по основной аппаратной шне I2C, так как ей была указана ссылка &Wire.
#include <Wire.h>                  // Подключаем библиотеку Wire для работы с аппаратными шинами I2C, до подключения библиотеки iarduino_AM2320.
#include <iarduino_AM2320.h>       // Подключаем библиотеку iarduino_AM2320 для работы с датчиком влажности и температуры AM2320.
iarduino_AM2320 sensor;            // Создаём объект sensor для работы с датчиком AM2320, используя функции и методы библиотеки iarduino_AM2320.
                                   //
void setup(){                      //
     sensor.begin(&Wire);          // Инициируем работу с датчиком AM2320, указав ссылку на объект для работы с шиной I2C на которой находится датчик.
}                                  //
                                   //
void loop(){                       //
     sensor.read();                // Читаем показания датчика.
     float t = sensor.tem;         // Получаем температуру.
     float h = sensor.hum;         // Получаем влажность.
}                                  //
- Программная шина:
В  примере библиотека iarduino_AM2320 для работы с датчиком AM2320 будет работать по программной шне I2C, так как ей была указана ссылка &sWire.
#include <iarduino_I2C_Software.h> // Подключаем библиотеку для работы с программной шиной I2C, до подключения библиотеки iarduino_AM2320.
SoftTwoWire sWire(3,4);            // Создаём объект sWire для работы с программной шиной I2C указав выводы которым будет назначена роль линий: SDA, SCL.
                                   //
#include <iarduino_AM2320.h>       // Подключаем библиотеку iarduino_AM2320 для работы с датчиком влажности и температуры AM2320.
iarduino_AM2320 sensor;            // Создаём объект sensor для работы с датчиком AM2320, используя функции и методы библиотеки iarduino_AM2320.
                                   //
void setup(){                      //
     sensor.begin(&sWire);         // Инициируем работу с датчиком AM2320, указав ссылку на объект для работы с шиной I2C на которой находится датчик.
}                                  //
                                   //
void loop(){                       //
     sensor.read();                // Читаем показания датчика.
     float t = sensor.tem;         // Получаем температуру.
     float h = sensor.hum;         // Получаем влажность.
}                                  //
Более подробно о библиотеках iarduino работающих с модулями по шине I2C можно ознакомиться на странице Wiki - расширенные возможности библиотек iarduino для шины I2C.
Описание функций библиотеки:
В данном разделе описаны функции библиотеки iarduino_I2C_Software для создания и работы с программными шинами I2C.
Функции данной библиотеки полностью совместимы с функциями библиотекой Wire для работы с аппаратной шиной I2C в качестве мастера.
Подключение библиотеки:
- Указание выводов при создании объекта:
#include <iarduino_I2C_Software.h> // Подключаем библиотеку для работы с программной шиной I2C. SoftTwoWire sWire(3,4); // Создаём объект sWire, указав выводы: SDA, SCL. // SoftTwoWire sWire1(5,6); // Можно создать несколько объектов, а значит несколько шин.
- Указание выводов после создания объекта:
#include <iarduino_I2C_Software.h> // Подключаем библиотеку для работы с программной шиной I2C.
SoftTwoWire sWire;                 // Создаём объект sWire.
                                   //
void setup(){                      //
     sWire.setPins(3,4);           // Указываем выводы: SDA, SCL.
     sWire.begin();                // Инициируем работу в качестве мастера.
}                                  //
В большинстве случаев целесообразно указывать выводы сразу при создании объекта. Но бывают случаи когда выводы нужно назначить после совершения определённых действий. Например, ИК датчик температуры MLX90614 может работать в режиме I2C, а может выводить ШИМ на линию SDA, для отключения которого требуется подать импульс на вывод SCL длительностью 3 мс, значит назначать выводам роль линий SDA и SCL программной шины I2C целесообразно после проверки режима работы датчика.
Функция begin();
- Назначение: Инициализация работы с программной шиной I2C.
- Синтаксис:
- begin(); // Инициализация в роли ведущего (master).
- begin( АДРЕС ); // Инициализация в роли ведомого (slave).
- Параметры:- uint8_t АДРЕС - Адрес в роли ведомого на шине I2C.
 
- Возвращаемое значение: bool - результат инициализации (true или false).
- Примечание:
- Функцию достаточно вызвать однократно, но только если уже указаны выводы шины.
- Библиотека версии 1.0.4 и ниже, не поддерживает роль ведомого.
- Пример:
sWire.begin(); // Инициируем работу программной шины I2C в качестве мастера.
Функция setPins();
- Назначение: Указание выводов программной шины I2C.
- Синтаксис: setPins( SDA , SCL );
- Параметры:- int SDA - Номер вывода которому будет назначена роль линии SDA на шине I2C.
- int SCL - Номер вывода которому будет назначена роль линии SCL на шине I2C.
 
- Возвращаемое значение: bool - результат назначения ролей выводам (true или false).
- Примечание:
- Выводы указываются если они не были указаны при создании объекта или после отключения ранее указанных выводов функцией end().
- После указания выводов необходимо вызвать функцию begin().
- Выводы должны поддерживать ввод/вывод логических уровней.
- Выводы A0-A5 Arduino UNO поддерживают ввод/вывод логических уровней, значит их можно использовать на равне с выводами D0-D13.
- Пример:
sWire.setPins(3,4); // Указываем выводы программной шины (3-SDA,4-SCL).
Функция getPins();
- Назначение: Получение указанных ранее выводов программной шины I2C.
- Синтаксис: getPins(&SDA, &SCL);
- Параметры:- int &SDA - Адрес переменной в которую требуется сохранить номер вывода SDA.
- int &SCL - Адрес переменной в которую требуется сохранить номер вывода SCL.
 
- Возвращаемое значение: bool - результат записи в переменные (true или false).
- Примечание: Если выводы не указаны или отключены функцией end(), то значения переменных останутся без изменений, а функция вернёт false.
- Пример:
int i=0, j=0; // Объявляем переменные для получения ранее указанных номеров выводов SDA и SCL sWire.getPins(&i,&j); // Получаем номер вывода SDA в переменную i, SCL в переменную j.
Функция end();
- Назначение: Отключение выводов программной шины I2C.
- Синтаксис: end();
- Параметры: Нет.
- Возвращаемое значение: Нет.
- Примечание:
- Отключённые выводы будут сконфигурированы как логические входы.
- Для включения нужно вновь указать выводы setPins(), а потом вызвать begin().
- Пример:
sWire.end(); // Отключаем ранее указанные выводы SDA и SCL.
Функция setClock();
- Назначение: Указание скорости передачи данных.
- Синтаксис: setClock( ЧАСТОТА );
- Параметры:
- uint32_t ЧАСТОТА - Скорость тактирования линии SCL в Гц.
- Возвращаемое значение: Нет.
- Примечание:
- Функцию можно вызывать как до, так и после функции begin().
- За 1 такт SCL передаётся 1 бит SDA, значит 1 бит/с = 1 Гц.
- По умолчанию используется частота 100'000 Гц.
- Библиотека версии 1.0.4 и ниже не использует таймеры и прерывания, а значит реальная частота тактирования линии SCL может немного отличаться от заданной.
- Можно указывать любую частоту от 1 Гц и выше, но реальная частота будет зависеть от производительности микроконтроллера и самого медленного устройства на шине, если оно поддерживает функцию удержания линии SCL.
- Документированные частоты:
- Стандартный режим: 100'000 Гц.
- Быстрый режим: 400'000 Гц.
- Быстрый режим плюс: 1'000'000 Гц.
- Высокоскоростной режим: 1'700'000 и 3'400'000 Гц.
- Сверхбыстрый режим: 5'000'000 Гц.
- Пример:
sWire.setClock(400000); // Перейти на частоту 400 кГц (быстрый режим).
Функция setWireTimeout();
- Назначение: Указание максимального времени ожидания ведомого.
- Синтаксис: setWireTimeout( ВРЕМЯ [ ,СБРОС ] );
- Параметры:
- uint32_t ВРЕМЯ - Максимальное время ожидания ведомого (timeout) в мкс.
- bool СБРОС - Необязательный флаг указывает отключить шину при достижении timeout.
- Возвращаемое значение: Нет.
- Примечание:
- По умолчанию ВРЕМЯ = 25'000 мкс, СБРОС = false.
- Если указать ВРЕМЯ = 0 мкс, то timeout отключён, ждать ведомого пока не ответит.
- Если флаг СБРОС не указан или равен false, то при достижении timeout ожидание ведомого завершится ошибкой и установится флаг сработавшего timeout, который нужно будет сбросить функцией clearWireTimeoutFlag().
- Если указать флаг СБРОС = true, то при достижении timeout, шина будет отключена, как при обращении к функции end() - отключение выводов.
- Пример:
sWire.setWireTimeout(10000); // Установить время ожидания ведомого в 10 мс. sWire.setWireTimeout(0); // Отключить timeout, ждать ведомого пока он не ответит. sWire.setWireTimeout(50000,true); // Ждать ведомого 50 мс, если не ответит отключить шину.
Функция getWireTimeoutFlag();
- Назначение: Получить флаг сработавшего timeout ожидания ведомого.
- Синтаксис: getWireTimeoutFlag();
- Параметры: Нет
- Возвращаемое значение: bool ФЛАГ сработавшего timeout (true или false).
- Примечание:
- Время ожидания ведомого задаётся функцией setWireTimeout().
- Если достигнут timeout ожидания ведомого, то нужно его сбросить clearWireTimeoutFlag().
Функция clearWireTimeoutFlag();
- Назначение: Сбросить флаг сработавшего timeout ожидания ведомого.
- Синтаксис: clearWireTimeoutFlag();
- Параметры: Нет
- Возвращаемое значение: Нет.
- Примечание:
- Проверить состояние флага сработавшего timeout можно функцией getWireTimeoutFlag().
- Функция указания времени setWireTimeout() так же сбрасывает этот флаг.
- Пример:
if( sWire.getWireTimeoutFlag() ){ // Если установлен флаг сработавшего timeout ожидания ведомого
    sWire.clearWireTimeoutFlag(); // Сбрасываем флаг сработавшего timeout ожидания ведомого
}                                 //
Функция beginTransmission();
- Назначение: Инициация передачи данных ведомому с указанием его адреса.
- Синтаксис: beginTransmission( АДРЕС );
- Параметры:
- uint8_t АДРЕС ведомого (от 0x00 до 0x7F).
- Возвращаемое значение: Нет.
- Примечание:
- Функция не начинает передачу данных по шине I2C, а инициирует её, то есть запоминает адрес ведомого и готовит буфер к получению данных для передачи функцией write().
Функция write();
- Назначение: Помещение данных в буфер для передачи.
- Синтаксис:
- write( БАЙТ ); // Помещение в буфер для передачи одного байта.
- write( МАССИВ, КОЛИЧЕСТВО ); // Помещение в буфер нескольких байт из массива.
- Параметры:
- uint8_t БАЙТ для помещения в буфер для передачи.
- uint8_t МАССИВ байтов для помещения в буфер для передачи.
- size_t КОЛИЧЕСТВО байт указанного массива для помещения в буфер для передачи.
- Возвращаемое значение: size_t Количество реально помещённых байт в буфер для передачи.
- Примечание:
- Функция не передаёт данные по шине I2C, а помещает их в буфер для передачи.
- Размер буфера определён идентификатором SOFT_I2C_BUFFER_LENGTH = 32 байта. Его можно изменить в начале файла iarduino_I2C_Software.h
- Функция возвращает не общее количество байт в буфере, а количество байт помещённых в буфер текущим обращением к данной функции.
Функция endTransmission();
- Назначение: Выполнение инициированной ранее передачи данных из буфера ведомому.
- Синтаксис: endTransmission( [СТОП] );
- Параметры:
- bool СТОП - Необязательный флаг указывает установить сигнал Stop после передачи.
- Возвращаемое значение: uint8_t РЕЗУЛЬТАТ передачи данных ведомому.
- 0 - Передача успешно завершена.
- 1 - Переполнен буфер для передачи.
- 2 - Получен NACK при передаче адреса (ведомый отсутствует).
- 3 - Получен NACK при передаче данных (ошибка ведомого, помехи на шине и т.д.).
- 4 - Другая ошибка.
- 5 - Превышен timeout ожидания ведомого (ведомый не отвечает).
- Примечание:
- Если флаг СТОП не указан или равен true, то после завершения передачи данных на шине I2C будет установлен сигнал Stop (освобождение шины).
- Если флаг СТОП равен false, то после завершения передачи данных шина останется занята мастером. Значит сигнал Start отправленный в новом пакете данных по шине I2C будет расценен ведомыми как сигнал ReStart.
- Пример:
uint8_t i[] = {1,2,3};         // Создаём массив для передачи данных ведомому.
sWire.beginTransmission(0x09); // Инициируем передачу данных ведомому с адресом 0x09.
sWire.write(5);                // Помещаем в буфер для передачи один байт = 5.
sWire.write(i, 3);             // Помещаем в буфер для передачи 3 байта из массива i.
sWire.endTransmission();       // Выполняем инициированную ранее передачу данных.
Функция requestFrom();
- Назначение: Чтение указанного количества байт ведомого в буфер.
- Синтаксис: requestFrom( АДРЕС , КОЛИЧЕСТВО [, СТОП ] );
- Параметры:
- uint8_t АДРЕС ведомого (от 0x00 до 0x7F).
- uint8_t КОЛИЧЕСТВО читаемых байт ведомого в буфер.
- bool СТОП - Необязательный флаг указывает установить сигнал Stop после чтения.
- Возвращаемое значение: uint8_t - Количество прочитанных байт по шине I2C.
- Примечание:
- Функция выполняет чтение указанного количества байт ведомого по шине I2C в буфер. Количество байт в буфере можно узнать функцией available(), а прочитать данные можно функциями read() или peek().
- Если флаг СТОП не указан или равен true, то после завершения чтения данных на шине I2C будет установлен сигнал Stop (освобождение шины).
- Если флаг СТОП равен false, то после завершения чтения данных шина останется занята мастером. Значит сигнал Start отправленный в новом пакете данных по шине I2C будет расценен ведомыми как сигнал ReStart.
- Размер буфера определён идентификатором SOFT_I2C_BUFFER_LENGTH = 32 байта. Его можно изменить в начале файла iarduino_I2C_Software.h
Функция available();
- Назначение: Возвращает количество байт, доступных для чтения из буфера.
- Синтаксис: available();
- Параметры: Нет.
- Возвращаемое значение: int - Количество байт в буфере для чтения.
Функция read();
- Назначение: Возвращает очередной байт из буфера для чтения.
- Синтаксис: read();
- Параметры: Нет.
- Возвращаемое значение: int - байт.
- Примечание:
- Данные читаются в буфер по шине I2C функцией requestFrom(), а читаются из буфера функцией rear() по принципу «первым пришёл - первым ушёл» (FIFO) first in, first out.
- Функция read() читает 1 байт не по шине I2C, а из буфера уже прочитанных данных.
- Каждый прочитанный байт функцией read() удаляется из буфера.
- Пример:
sWire.requestFrom(0x09, 3);   // Читаем 3 байта ведомого с адресом 0x09.
while( sWire.available() ){   // Если в буфере остались данные...
    int i = sWire.read();     // Читаем очередной байт из буфера.
    Serial.println( i );      // Выводим прочитанный байт.
}                             //
Функция peek();
- Назначение: Возвращает очередной байт из буфера для чтения.
- Синтаксис: peek();
- Параметры: Нет.
- Возвращаемое значение: int - байт.
- Примечание: В отличии от rear(), функция peek() не удаляет байт из буфера.
- Пример:
if( sWire.peek()<10 ){ Serial.print( 0 ); } // Если число в буфере меньше 10, то выводим ведущий 0.
Serial.println( sWire.read() ); // Выводим то же число, что ранее сравнивали с 10.
Функция flush();
- Синтаксис: flush();
- Параметры: Нет.
- Возвращаемое значение: Нет.
- Примечание: Библиотека версии 1.0.4 и ниже, не поддерживает эту функцию.
- Пример:
sWire.flush();
Функция onReceive();
- Назначение: Указание функции обработки полученных данных от мастера.
- Синтаксис: onReceive( ФУНКЦИЯ );
- Параметры:
- void (*)(int) ФУНКЦИЯ - Имя функции обработки полученных данных от мастера.
- Возвращаемое значение: Нет.
- Примечание:
- Функция предназначена для ведомого устройства.
- Функция указывает на функцию обработки полученных данных от мастера.
- Указанная функция (обработчик) будет вызываться каждый раз после завершения приема данных от мастера.
- Функция обработки полученных данных от мастера должна принимать в качестве единственного параметра типа int - Количество принятых байт данных от мастера.
- Библиотека версии 1.0.4 и ниже, не поддерживает эту функцию.
- Пример:
void fnc(int sum){             // sum - количество принятых байт от мастера.
     for(int i=0; i<sum; i++){ // Проходим по всем принятым от мастера байтам...
         int j = sWire.read(); // Читаем очередной байт из буфера.
         ...                   // Выполняем требуемые действия с байтом.
     }                         //
}                              //
sWire.onReceive( fnc );        // Указываем функцию обработки.
Функция onRequest();
- Назначение: Указание функции обработки получения запроса от мастера.
- Синтаксис: onRequest( ФУНКЦИЯ );
- Параметры:
- void (*)(void) ФУНКЦИЯ - Имя функции обработки получения запроса от мастера.
- Возвращаемое значение: Нет.
- Примечание:
- Функция предназначена для ведомого устройства.
- Функция указывает на функцию обработки получения запроса от мастера.
- Указанная функция (обработчик) будет вызываться каждый раз когда мастер запрашивает чтение очередного байта от ведомого.
- Библиотека версии 1.0.4 и ниже, не поддерживает эту функцию.
- Пример:
void fnc(void){         //
     sWire.write( i );  // Помещаем в буфер для передачи мастеру один байт i.
}                       //
sWire.onRequest( fnc ); // Указываем функцию обработки запроса от мастера.

Обсуждение