Mega2560
D20 (SDA) и D21 (SCL)
—
Due
D20 (SDA) и D21 (SCL)
Модель Due имеет вторую пару контактов I2C, подписанных SDA1 и SCL1
Протокол I2C
Для передачи и приема данных через интерфейс I2C используются две линии (отсюда второе название — двухпроводной интерфейс, Two Wire Interface). Эти две линии называют также тактовой линией (Serial Clock Line, SCL) и линией данных (Serial Data Line, SDA). На рис. 7.4 изображена временная диаграмма сигнала, передаваемого через интерфейс I2C.
Рис. 7.4. Временная диаграмма сигнала, передаваемого через интерфейс I2C
Ведущее устройство генерирует тактовые импульсы на линии SCL, и, когда имеются данные для передачи, отправитель (ведущее или ведомое устройство) выводит линию SDA из третьего состояния (в режим цифрового выхода) и посылает данные в виде логических нулей и единиц в моменты положительных импульсов тактового сигнала. По окончании передачи вывод тактовых импульсов может быть остановлен, и линия SDA возвращается в третье состояние.
Библиотека Wire
Можно, конечно, генерировать описанные ранее импульсы самостоятельно, управляя битами, то есть включая и выключая цифровые выходы программно. Но чтобы упростить нам жизнь, в составе программного обеспечения для Arduino имеется библиотека Wire, принимающая на себя все сложности, связанные с синхронизацией, и позволяющая нам просто посылать и принимать байты данных.
Чтобы задействовать библиотеку Wire, ее сначала нужно подключить командой
#include <Wire.h>
Инициализация I2C
В большинстве случаев плата Arduino играет роль ведущего устройства на любой шине I2C. Чтобы инициализировать Arduino как ведущее устройство, нужно выполнить команду begin в функции setup, как показано далее:
void setup()
{
Wire.begin();
}
Обратите внимание: поскольку в данном случае плата Arduino действует как ведущее устройство, ей не нужно присваивать адрес. Если бы плата настраивалась на работу в режиме ведомого устройства, нам пришлось бы присвоить адрес в диапазоне от 0 до 127, передав его как параметр, чтобы уникально идентифицировать плату на шине I2C.
Отправка данных ведущим устройством
Чтобы отправить данные устройству на шине I2C, сначала нужно выполнить функцию beginTransmission и передать ей адрес устройства-получателя:
Wire.beginTransmission(4);
Отправка данных устройствам на шине I2C может производиться побайтно или целыми массивами типа char, как показано в следующих двух примерах:
Wire.send(123); // передача байта со значением 123
Wire.send("ABC"); // передача строки символов "ABC"
По окончании передачи должна вызываться функция endTransmission:
Wire.endTransmission();
Прием данных ведущим устройством
Чтобы принять данные от ведомого устройства, сначала нужно указать количество ожидаемых байтов вызовом функции requestFrom:
Wire.requestFrom(4, 6); // запросить 6 байт у устройства с адресом 4
В первом аргументе этой функции передается адрес ведомого устройства, от которого ведущее устройство желает получить данные, а во втором аргументе — количество байтов, которое ожидается получить. Ведомое устройство может передать меньшее количество байтов, поэтому, чтобы определить, были ли получены данные и сколько байтов действительно получено, необходимо использовать функцию available. Следующий пример (взят из пакета примеров, входящих в состав библиотеки Wire) демонстрирует, как ведущее устройство принимает все полученные данные и выводит их в монитор последовательного порта:
#include <Wire.h>
void setup() {
Wire.begin(); // подключиться к шине i2c (для ведущего
// устройства адрес не указывается)
Serial.begin(9600); // инициализировать монитор последовательного порта
}
void loop() {
Wire.requestFrom(8, 6); // запросить 6 байт у ведомого устройства #8
while (Wire.available()) { // ведомое устройство может прислать меньше
char c = Wire.read(); // принять байт как символ
Serial.print(c); // вывести символ
}
delay(500);
}
Библиотека Wire автоматически буферизует входящие данные.
Примеры использования I2C
Любое устройство I2C должно иметь сопроводительное техническое описание, где перечисляются поддерживаемые им сообщения. Такие описания необходимы, чтобы конструировать сообщения для отправки ведомым устройствам и интерпретировать их ответы. Однако для многих устройств I2C, которые можно подключить к плате Arduino, существуют специализированные библиотеки, обертывающие сообщения I2C в простые и удобные функции. Фактически, если вам придется работать с каким-то устройством, для которого отсутствует специализированная библиотека, опубликуйте собственную библиотеку для всеобщего использования и заработайте себе несколько очков в карму.