КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Работа с программной шиной I2C

Общие сведения:

Шина 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 ); // Указываем функцию обработки запроса от мастера.

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями