Библиотека Wire для Arduino для работы с шиной I2C. PCF8574P: подключение кнопок к Arduino по шине I2C или Люк Скайуокер наносит удар

С номиналами от 10 Ом до 1 МОм);

  • 2 резистора по 4,7 кОм (из того же набора);
  • соединительные провода (например, вот хороший набор);
  • компьютер с Arduino IDE.
  • 1 Описание интерфейса I2C

    Последовательный протокол обмена данными IIC (также называемый I2C - Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock) . Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.

    В сети есть хотя бы одно ведущее устройство (Master) , которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave) , которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».

    Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.

    Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства , с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 2 7 = 128 минус нулевой адрес). Следующий бит посылки - это код операции (чтение или запись) и ещё один бит - бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.

    Это проиллюстрировано на рисунке ниже.. В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.


    Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит - бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.

    2 Реализация I2C в Arduino

    Arduino использует для работы по интерфейсу I2C два порта. Например, в Arduino UNO и Arduino Nano аналоговый порт A4 соответствует SDA, аналоговый порт A5 соответствует SCL.


    Для других моделей плат соответствие выводов такое:

    3 Библиотека "Wire" для работы с IIC

    Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire . Она имеет следующие функции:

    Функция Назначение
    begin(address) инициализация библиотеки и подключение к шине I2C; если не указан адрес, то присоединённое устройство считается ведущим; используется 7-битная адресация;
    requestFrom() используется ведущим устройством для запроса определённого количества байтов от ведомого;
    beginTransmission(address) начало передачи данных к ведомому устройству по определённому адресу;
    endTransmission() прекращение передачи данных ведомому;
    write() запись данных от ведомого в ответ на запрос;
    available() возвращает количество байт информации, доступных для приёма от ведомого;
    read() чтение байта, переданного от ведомого ведущему или от ведущего ведомому;
    onReceive() указывает на функцию, которая должна быть вызвана, когда ведомое устройство получит передачу от ведущего;
    onRequest() указывает на функцию, которая должна быть вызвана, когда ведущее устройство получит передачу от ведомого.

    4 Подключение I2C устройства к Arduino

    Давайте посмотрим, как работать с шиной I2C с помощью Arduino.

    Сначала соберём схему, как на рисунке. Будем управлять яркостью светодиода, используя цифровой 64-позиционный потенциометр AD5171 (см. техническое описание), который подключается к шине I2C. Адрес, по которому мы будем обращаться к потенциометру - 0x2c (44 в десятичной системе).


    5 Управление устройством по шине IIC

    Рассмотрим диаграммы информационного обмена с цифровым потенциометром AD5171, представленные в техническом описании:


    Нас тут интересует диаграмма записи данных в регистр RDAC . Этот регистр используется для управления сопротивлением потенциометра.

    Откроем из примеров библиотеки "Wire" скетч: Файл Образцы Wire digital_potentiometer . Загрузим его в память Arduino.

    #include // подключаем библиотеку "Wire" byte val = 0; // значение для передачи потенциометру void setup() { Wire.begin(); // подключаемся к шине I2C как мастер } void loop() { Wire.beginTransmission(44); // начинаем обмен с устройством с I2C адресом "44" (0x2C) Wire.write(byte(0x00)); // посылаем инструкцию записи в регистр RDAC Wire.write(val); // задаём положение 64-позиционного потенциометра Wire.endTransmission(); // завершаем I2C передачу val++; // инкрементируем val на 1 if (val == 63) { // по достижении максимума потенциометра val = 0; // сбрасываем val } delay(500); }

    После включения вы видите, как яркость светодиода циклически нарастает, а потом гаснет. При этом мы управляем потенциометром с помощью Arduino по шине I2C.

    LCD дисплей частый гость в проектах ардуино. Но в сложных схемах у нас может возникнуть проблема недостатка портов Arduino из-за необходимости подключить экран, у которого очень очень много контактов. Выходом в этой ситуации может стать I2C /IIC переходник, который подключает практически стандартный для Arduino экран 1602 к платам Uno, Nano или Mega всего лишь при помощи 4 пинов. В этой статье мы посмотрим, как можно подключить LCD экран с интерфейсом I2C, какие можно использовать библиотеки, напишем короткий скетч-пример и разберем типовые ошибки.

    Жидкокристаллический дисплей (Liquid Crystal Display) LCD 1602 является хорошим выбором для вывода строк символов в различных проектах. Он стоит недорого, есть различные модификации с разными цветами подсветки, вы можете легко скачать готовые библиотеки для скетчей Ардуино. Но самым главным недостатком этого экрана является тот факт, что дисплей имеет 16 цифровых выводов, из которых обязательными являются минимум 6. Поэтому использование этого LCD экрана без i2c добавляет серьезные ограничения для плат Arduino Uno или Nano. Если контактов не хватает, то вам придется покупать плату Arduino Mega или же сэкономить контакты, в том числе за счет подключения дисплея через i2c.

    Краткое описание пинов LCD 1602

    Давайте посмотрим на выводы LCD1602 повнимательней:

    Каждый из выводов имеет свое назначение:

    1. Земля GND;
    2. Питание 5 В;
    3. Установка контрастности монитора;
    4. Команда, данные;
    5. Записывание и чтение данных;
    6. Enable;

    7-14. Линии данных;

    1. Плюс подсветки;
    2. Минус подсветки.

    Технические характеристики дисплея:

    • Символьный тип отображения, есть возможность загрузки символов;
    • Светодиодная подсветка;
    • Контроллер HD44780;
    • Напряжение питания 5В;
    • Формат 16х2 символов;
    • Диапазон рабочих температур от -20С до +70С, диапазон температур хранения от -30С до +80 С;
    • Угол обзора 180 градусов.

    Схема подключения LCD к плате Ардуино без i2C

    Стандартная схема присоединения монитора напрямую к микроконтроллеру Ардуино без I2C выглядит следующим образом.

    Из-за большого количества подключаемых контактов может не хватить места для присоединения нужных элементов. Использование I2C уменьшает количество проводов до 4, а занятых пинов до 2.

    Где купить i2c 1602 экраны для ардуино

    LCD экран 1602 довольно популярен, поэтому вы без проблем сможете найти его как в отечественных интернет-магазинах, так и на зарубежных площадках. Приведем несколько ссылок на наиболее доступные варианты:

    • Вариант обычного дисплея от довольно известного продавца Wavgat по цене ниже 100 рублей.
    • Комплект экрана и i2c адаптера (нужно спаять самим). Цена – ниже 200 рублей
    • Шилд i2c экрана – модуль LCD 1602 с управляющими кнопками и платой расширения .

    Описание протокола I2C

    Прежде чем обсуждать подключение дисплея к ардуино через i2c-переходник, давайте вкратце поговорим о самом протоколе i2C.

    I2C / IIC (Inter-Integrated Circuit) – это протокол, изначально создававшийся для связи интегральных микросхем внутри электронного устройства. Разработка принадлежит фирме Philips. В основе i2c протокола является использование 8-битной шины, которая нужна для связи блоков в управляющей электронике, и системе адресации, благодаря которой можно общаться по одним и тем же проводам с несколькими устройствами. Мы просто передаем данные то одному, то другому устройству, добавляя к пакетам данных идентификатор нужного элемента.

    Самая простая схема I2C может содержать одно ведущее устройство (чаще всего это микроконтроллер Ардуино) и несколько ведомых (например, дисплей LCD). Каждое устройство имеет адрес в диапазоне от 7 до 127. Двух устройств с одинаковым адресом в одной схеме быть не должно.

    Плата Arduino поддерживает i2c на аппаратном уровне. Вы можете использовать пины A4 и A5 для подключения устройств по данному протоколу.

    В работе I2C можно выделить несколько преимуществ:

    • Для работы требуется всего 2 линии – SDA (линия данных) и SCL (линия синхронизации).
    • Подключение большого количества ведущих приборов.
    • Уменьшение времени разработки.
    • Для управления всем набором устройств требуется только один микроконтроллер.
    • Возможное число подключаемых микросхем к одной шине ограничивается только предельной емкостью.
    • Высокая степень сохранности данных из-за специального фильтра подавляющего всплески, встроенного в схемы.
    • Простая процедура диагностики возникающих сбоев, быстрая отладка неисправностей.
    • Шина уже интегрирована в саму Arduino, поэтому не нужно разрабатывать дополнительно шинный интерфейс.

    Недостатки:

    • Существует емкостное ограничение на линии – 400 пФ.
    • Трудное программирование контроллера I2C, если на шине имеется несколько различных устройств.
    • При большом количестве устройств возникает трудности локализации сбоя, если одно из них ошибочно устанавливает состояние низкого уровня.

    Модуль i2c для LCD 1602 Arduino

    Самый быстрый и удобный способ использования i2c дисплея в ардуино – это покупка готового экрана со встроенной поддержкой протокола. Но таких экранов не очень много истоят они не дешево. А вот разнообразных стандартных экранов выпущено уже огромное количество. Поэтому самым доступным и популярным сегодня вариантом является покупка и использование отдельного I2C модуля – переходника, который выглядит вот так:

    С одной стороны модуля мы видим выводы i2c – земля, питание и 2 для передачи данных. С другой переходника видим разъемы внешнего питания. И, естественно, на плате есть множество ножек, с помощью которых модуль припаивается к стандартным выводам экрана.


    Для подключения к плате ардуино используются i2c выходы. Если нужно, подключаем внешнее питание для подстветки. С помощью встроенного подстроечного резистора мы можем настроить настраиваемые значения контрастности J

    На рынке можно встретить LCD 1602 модули с уже припаянными переходниками, их использование максимально упощено. Если вы купили отдельный переходник, нужно будет предварительно припаять его к модулю.

    Подключение ЖК экрана к Ардуино по I2C

    Для подключения необходимы сама плата Ардуино, дисплей, макетная плата, соединительные провода и потенциометр.

    Если вы используете специальный отдельный i2c переходник, то нужно сначала припаять его к модулю экрана. Ошибиться там трудно, можете руководствоваться такой схемой.


    Жидкокристаллический монитор с поддержкой i2c подключается к плате при помощи четырех проводов – два провода для данных, два провода для питания.

    • Вывод GND подключается к GND на плате.
    • Вывод VCC – на 5V.
    • SCL подключается к пину A5.
    • SDA подключается к пину A.

    И это все! Никаких паутин проводов, в которых очень легко запутаться. При этом всю сложность реализации i2C протокола мы можем просто доверить библиотекам.

    Библиотеки для работы с i2c LCD дисплеем

    Для взаимодействие Arduino c LCD 1602 по шине I2C вам потребуются как минимум две библиотеки:

    • Библиотека Wire.h для работы с I2C уже имеется в стандартной программе Arduino IDE.
    • Библиотека LiquidCrystal_I2C.h, которая включает в себя большое разнообразие команд для управления монитором по шине I2C и позволяет сделать скетч проще и короче. Нужно дополнительно установить библиотеку После подключения дисплея нужно дополнительно установить библиотеку LiquidCrystal_I2C.h

    После подключения к скетчу всех необходимых библиотек мы создаем объект и можем использовать все его функции. Для тестирования давайте загрузим следующий стандартный скетч из примера.

    #include #include // Подключение библиотеки //#include // Подключение альтернативной библиотеки LiquidCrystal_I2C lcd(0x27,16,2); // Указываем I2C адрес (наиболее распространенное значение), а также параметры экрана (в случае LCD 1602 - 2 строки по 16 символов в каждой //LiquidCrystal_PCF8574 lcd(0x27); // Вариант для библиотеки PCF8574 void setup() { lcd.init(); // Инициализация дисплея lcd.backlight(); // Подключение подсветки lcd.setCursor(0,0); // Установка курсора в начало первой строки lcd.print("Hello"); // Набор текста на первой строке lcd.setCursor(0,1); // Установка курсора в начало второй строки lcd.print("ArduinoMaster"); // Набор текста на второй строке } void loop() { }

    Описание функций и методов библиотеки LiquidCrystal_I2C:

    • home() и clear() – первая функция позволяет вернуть курсор в начало экрана, вторая тоже, но при этом удаляет все, что было на мониторе до этого.
    • write(ch) – позволяет вывести одиночный символ ch на экран.
    • cursor() и noCursor() – показывает/скрывает курсор на экране.
    • blink() и noBlink() – курсор мигает/не мигает (если до этого было включено его отображение).
    • display() и noDisplay() – позволяет подключить/отключить дисплей.
    • scrollDisplayLeft() и scrollDisplayRight() – прокручивает экран на один знак влево/вправо.
    • autoscroll() и noAutoscroll() – позволяет включить/выключить режим автопрокручивания. В этом режиме каждый новый символ записывается в одном и том же месте, вытесняя ранее написанное на экране.
    • leftToRight() и rightToLeft() – Установка направление выводимого текста – слева направо или справа налево.
    • createChar(ch, bitmap) – создает символ с кодом ch (0 – 7), используя массив битовых масок bitmap для создания черных и белых точек.

    Альтернативная библиотека для работы с i2c дисплеем

    В некоторых случаях при использовании указанной библиотеки с устройствами, оснащенными контроллерами PCF8574 могут возникать ошибки. В этом случае в качестве альтернативы можно предложить библиотеку LiquidCrystal_PCF8574.h. Она расширяет LiquidCrystal_I2C, поэтому проблем с ее использованием быть не должно.

    Проблемы подключения i2c lcd дисплея

    Если после загрузки скетча у вас не появилось никакой надписи на дисплее, попробуйте выполнить следующие действия.

    Во-первых, можно увеличить или уменьшить контрастность монитора. Часто символы просто не видны из-за режима контрастности и подсветки.

    Если это не помогло, то проверьте правильность подключения контактов, подключено ли питание подсветки. Если вы использовали отдельный i2c переходник, то проверьте еще раз качество пайки контактов.

    Другой часто встречающейся причиной отсутствия текста на экране может стать неправильный i2c адрес. Попробуйте сперва поменять в скетче адрес устройства с 0x27 0x20 или на 0x3F. У разных производителей могут быть зашиты разные адреса по умолчанию. Если и это не помогло, можете запустить скетч i2c сканера, который просматривает все подключенные устройства и определяет их адрес методом перебора. Пример скетча i2c сканера .

    Если экран все еще останется нерабочим, попробуйте отпаять переходник и подключить LCD обычным образом.

    Заключение

    В этой статье мы рассмотрели основные вопросы использования LCD экрана в сложных проектах ардуино, когда нам нужно экономить свободные пины на плате. Простой и недорогой переходник i2c позволит подключить LCD экран 1602, занимая всего 2 аналоговых пина. Во многих ситуациях это может быть очень важным. Плата за удобство – необходимость в использовании дополнительного модуля – конвертера и библиотеки. На наш взгляд, совсем не высокая цена за удобство и мы крайне рекомендуем использовать эту возможность в проектах.

    Решил я сделать текстовую панель оператора(HMI) и подключить ее по «квадратной» шине I2C к Arduino. Для этого разработал на основе микросхемы PCF8574P плату клавиатуры из 5 кнопок.

    PCF8574P это расширитель портов, корпус DIP, работает по шине I2C. Приобрел я партию из двух таких микросхем за 0.94$ с бесплатной доставкой из Китая, таким образом одна штука стоит 0.47$. Покупка выгодная, так как в местных магазинах эти же микросхемы стоят больше 2 долларов за штуку.

    Дисплеем HMI будет стандартный экранчик 1602, так же через платку FC-113 работающий по квадратной шине.

    PCF8574P выслали, дали трек-номер и через 2 недели я их уже получил на почте.


    Извлекаем из пластиковой трубки, вроде бы все нормально.


    Однако, снизу на корпусе одной из микросхем есть следы загадочных термомеханических воздействий.


    Природа этих повреждений мне не ясна, но очевидно, что во время пересылки они появиться не могли.

    Долго думал над этой загадкой, пока меня не осенило.
    Просто на склад продавца пробрался Люк Скайуокер, вдруг уменьшившийся до микроскопических размеров. Там он приметил один из расширителей портов, спутал с имперским шагоходом и принялся рубить его световым мечем. Тут зашла комплектовальщица, увидела эту картину и такая говорит: «Прекрати, Люк Скайуокер! Это не имперский шагоход, это микросхема PCF8574P, за которую уже уплочено из Запорожья».

    Хорошо хоть, обе микросхемы при проверке оказались рабочими.

    Приступаем к созданию самой клавиатуры по такой схеме.


    В Layout 6.0 нарисовал одностороннюю плату.


    Скачать файл с платой можно .

    Плату травил перекисью водорода и лимонной кислотой.

    В сети много рецептов травления платы перекисью.
    Я делал такой раствор: 100 мл перекиси водорода 3%, 50 г лимонной кислоты, 3 чайные ложки соли. Баночку с перекисью подогрел в кастрюле с водой.

    Погружаем плату в раствор рисунком вниз, как рекомендуют при травлении перекисью.

    Пшшшшшш! Сначала процесс идет бурно.


    Пс… Потом заметно стихает. Переворачиваем, смотрим на рисунок.


    Красота.


    Готовая плата выглядит так.




    Адресные ножки микросхемы подключены на GND, поэтому адрес платы на шине будет 0x20.

    Пишем программу для Ардуино.

    #include
    #include

    #define led 13
    #define ADDR_KBRD 0x20
    #define ADDR_LCD 0x27

    String str;
    byte dio_in;
    bool b;
    bool key;

    LiquidCrystal_I2C lcd(ADDR_LCD,16,2); // Устанавливаем дисплей

    Void setup()
    {
    pinMode(13, OUTPUT);
    lcd.init();
    lcd.backlight();// Включаем подсветку дисплея
    Wire.begin();

    Wire.beginTransmission(ADDR_KBRD);
    Wire.write(B11111111);
    Wire.endTransmission();
    Serial.begin(9600);
    }
    void loop()
    {
    Wire.requestFrom(ADDR_KBRD,1);
    while (!Wire.available());
    byte dio_in = Wire.read(); //читаем состояние портов PCF8574P
    byte mask=1;
    for(int i=0; i<5;i++)
    {
    key[i]=!(dio_in & mask);
    mask=mask<<1;
    }

    Str=String(dio_in, BIN); //
    Serial.println(str);

    B=!b;
    digitalWrite(led, b);

    //
    lcd.setCursor(0, 0);
    lcd.print(String(key)+" "+
    String(key)+" "+
    String(key)+" "+
    String(key)+" "+
    String(key)+" "
    );
    delay(100);
    }


    Загружаем программу в Ардуино и подключаем его к созданной клавиатурной плате и дисплею.

    Включаем, работает!


    Мой HMI будет работать не просто с Arduino, а с ардуино-совместимым ПЛК . Если будет вдохновение и интерес читателей, напишу и про него как-нибудь.

    Плюсы PCF8574P:
    1. Минимальная обвязка.
    2. Прост в работе.

    Минусы PCF8574P:
    У самой микросхемы не обнаружил, хотя и советую покупать у другого продавца.

    На этом обзор микросхемы PCF8574P заканчиваю.
    Но как опытный уже обозреватель, заранее отвечу на вопросы, которые обязательно зададут:

    Почему в DIP корпусе? SOIC лучше.
    При прочих равных, я предпочитаю DIP, мне с ними проще.

    DIP и выводные элементы ставят только ламеры, все специалисты используют SOIC и SMD. Вот я паяю исключительно SMD и вообще я молодец.
    Вы молодец.

    Почему бы просто не купить на алиэкспрессе готовый модуль с дисплеем 1602 и клавиатурой 5 кнопок? Он тоже работает по I2C.
    Его цена от 11 $.
    Я же потратил:
    Дисплей 1602 - 1.3 $
    Плата FC-113 - 0.55 $
    Микросхема PCF8574P - 0.47 $
    Кнопки и колпачки - 0.7 $
    Реактивы для травления платы - 0.3 $
    Текстолит, резисторы и прочая мелочевка - бесплатно, из старых запасов.
    Итого: 3.32 $
    Но главное- на своей плате я поставил кнопки с квадратным толкателем что бы одеть на них красивые цветные колпачки.

    Ого, всего одна микросхема PCF8574P стоит почти как целая плата FC-113!
    Да уж…

    Вы сделали все неправильно. Неправильно рисовали, неправильно травили в неправильном растворе и поставили неправильные кнопки. Я бы на вашем месте сделал все правильно.
    Вы молодец.

    Почему пятая кнопка так далеко от остальных?
    Это специально так, они функционально различны. Те четыре это влево, вправо, отмена, ввод, а пятая будет SETUP.

    Я ждал более захватывающую историю про Люка Скайуокера, вы меня обманули!
    Я молодец.

    Описание библиотеки Wire

    Данная библиотека позволяет вам взаимодействовать с I2C / TWI устройствами. На платах Arduino с компоновкой R3 (распиновка 1.0) SDA (линия данных) и SCL (линия тактового сигнала) находятся на выводах около вывода AREF. Arduino Due имеет два I2C / TWI интерфейса: SDA1 и SCL1 находятся около вывода AREF, а дополнительные линии находятся на выводах 20 и 21.

    В таблице ниже показано, где расположены TWI выводы на разных платах Arduino.

    Начиная с Arduino 1.0, данная библиотека наследует функции Stream , что делает ее совместимой с другими библиотеками чтения/записи. Из-за этого send() и receive() были заменены на read() и write() .

    Примечание

    Существуют 7- и 8-битные версии адресов I2C. 7 битов идентифицируют устройство, а восьмой бит определяет, идет запись или чтение. Библиотека Wire использует 7 битные адреса. Если у вас есть техническое описание или пример кода, где используется 8-битный адрес, вам нужно откинуть младший бит (т.е. сдвинуть значение на один бит вправо), получив адрес от 0 до 127. Однако адреса от 0 до 7 не используются, так как зарезервированы, поэтому первым адресом, который может быть использован, является 8. Обратите внимание, что при подключении выводов SDA/SCL необходимы подтягивающие резисторы. Для более подробной информации смотрите примеры. На плате MEGA 2560 есть подтягивающие резисторы на выводах 20 и 21.

    Описание методов

    Wire.begin()

    Описание

    Инициализирует библиотеку Wire и подключается к шине I2C как ведущий (мастер) или ведомый. Как правило, должен вызываться только один раз.

    Синтаксис

    Wire.begin(address)

    Параметры

    address: 7-битный адрес ведомого устройства (необязательно); если не задан, плата подключается к шине как мастер.

    Возвращаемое значение

    Пример

    Примеры для ведомого устройства смотрите в примерах к методам onReceive() и onRequest() . Примеры для ведущего устройства смотрите в примерах к остальным методам. .

    Wire.requestFrom()

    Описание

    Используется мастером для запроса байтов от ведомого устройства. Эти байты могут быть получены с помощью методов available() и read() .

    Если этот аргумент равен true , то requestFrom() после запроса посылает сообщение STOP, освобождая шину I2C.

    Если этот аргумент равен false , то requestFrom() после запроса посылает сообщение RESTART. Шина не освобождается, что мешает другому устройству-мастеру влезть между сообщениями. Это позволяет одному ведущему устройству посылать несколько запросов, пока оно контролирует шину.

    Синтаксис

    Wire.requestFrom(address, quantity)

    Wire.requestFrom(address, quantity, stop)

    Параметры

    • address: 7-битный адрес устройства, у которого запрашиваются байты;
    • quantity: количество запрашиваемых байтов;
    • stop: boolean . true посылает сообщение STOP после запроса. false посылает сообщение RESTART после запроса, сохраняя соединение активным.
    Возвращаемое значение

    byte: количество байтов, возвращенных от ведомого устройства.

    Пример

    Wire.beginTransmission()

    Описание

    Начинает передачу на ведомое I2C устройство с заданным адресом. После него последовательность байтов для передачи ставится в очередь с помощью функции write() , и их передача с помощью вызова endTransmission() .

    Синтаксис

    Wire.beginTransmission(address)

    Параметры

    address: 7-битный адрес устройства, на которое необходимо передать данные.

    Возвращаемое значение

    Пример

    Wire.endTransmission()

    Описание

    Завершает передачу на ведомое устройство, которая была начата методом beginTransmission() и передает байты, которые были поставлены в очередь методом write() .

    Для совместимости с определенными I2C устройствами, начиная с Arduino 1.0.1, requestFrom() принимает аргумент логического типа данных, меняющий его поведение.

    Если этот аргумент равен true , то requestFrom() после передачи посылает сообщение STOP, освобождая шину I2C.

    Если этот аргумент равен false , то requestFrom() после передачи посылает сообщение RESTART. Шина не освобождается, что мешает другому устройству-мастеру влезть между сообщениями. Это позволяет одному ведущему устройству посылать несколько передач, пока оно контролирует шину.

    По умолчанию этот аргумент равен true .

    Синтаксис

    Wire.endTransmission()

    Wire.endTransmission(stop)

    Параметры

    stop: boolean . true посылает сообщение STOP после передачи. false посылает сообщение RESTART после передачи, сохраняя соединение активным.

    Возвращаемое значение

    byte , который указывает на состояние передачи:

    • 0: успех;
    • 1: данные слишком длинны для заполнения буфера передачи;
    • 2: принят NACK при передаче адреса;
    • 3: принят NACK при передаче данных;
    • 4: остальные ошибки.
    Пример

    Смотрите пример к методу write() .

    Wire.write()

    Описание

    Записывает данные от ведомого устройства в отклик на запрос от ведущего устройства, или ставит в очередь байты для передачи от мастера к ведомому устройству (между вызовами beginTransmission() и endTransmission()).

    Синтаксис

    Wire.write(value)

    Wire.write(string)

    Wire.write(data, length)

    Параметры

    • value: значение для передачи, один байт.
    • string: строка для передачи, последовательность байтов.
    • data: массив данных для передачи, байты.
    • length: количество байтов для передачи.
    Возвращаемое значение

    byte: write() возвращает количество записанных байтов, хотя чтение этого количества не обязательно.

    Пример #include byte val = 0; void setup() { Wire.begin(); // подключиться к шине i2c } void loop() { Wire.beginTransmission(44); // передача на устройство #44 (0x2c) // адрес устройства задан в техническом описании Wire.write(val); // отправить байт значения Wire.endTransmission(); // остановить передачу val++; // увеличить значение if(val == 64) // если дошли до 64-го значения (max) { val = 0; // начать с начала } delay(500); }

    Wire.available()

    Описание

    Возвращает количество байтов, доступных для получения с помощью read() . Этот метод должен вызываться на ведущем устройстве после вызова requestFrom() или на ведомом устройстве внутри обработчика onReceive() .

    Синтаксис

    Wire.available()

    Параметры

    Возвращаемое значение

    Количество байтов, доступных для чтения.

    Пример

    Смотрите пример к методу read() .

    Wire.read()

    Описание

    Считывает байт, который был передан от ведомого устройства к ведущему после вызова requestFrom() , или который был передан от ведущего устройства к ведомому.

    Синтаксис

    Параметры

    Возвращаемое значение

    byte: очередной принятый байт.

    Пример #include byte val = 0; void setup() { Wire.begin(); // подключиться к шине i2c (адрес для мастера не обязателен) Serial.begin(9600); // настроить последовательный порт для вывода } void loop() { Wire.requestFrom(2, 6); // запросить 6 байтов от ведомого устройства #2 while(Wire.available()) // ведомое устройство может послать меньше, чем запрошено { char c = Wire.read(); // принять байт как символ Serial.print(c); // напечатать символ } delay(500); }

    Wire.setClock()

    Описание

    Изменяет тактовую частоту для связи по шине I2C. У ведомых I2C устройств нет минимальной рабочей тактовой частоты, однако обычно используется 100 кГц.

    Синтаксис

    Wire.setClock(clockFrequency)

    Параметры

    clockFrequency: значение частоты (в герцах) тактового сигнала. Принимаются значения 100000 (стандартный режим) и 400000 (быстрый режим). Некоторые процессоры также поддерживают 10000 (низкоскоростной режим), 1000000 (быстрый режим плюс) и 3400000 (высокоскоростной режим). Чтобы убедиться, что необходимый режим поддерживается, обращайтесь к технической документации на конкретный процессор.

    Возвращаемое значение

    Wire.onReceive()

    Описание

    Регистрирует функцию, которая будет вызываться, когда ведомое устройство принимает передачу от мастера.

    Синтаксис

    Wire.onReceive(handler)

    Параметры

    handler: функция, которая должна будет вызываться, когда ведомое устройство принимает данные; она должна принимать один параметр int (количество байтов, прочитанных от мастера) и ничего не возвращать, т.е.:

    void myHandler(int numBytes)

    Возвращаемое значение

    Пример

    #include void setup() { Wire.begin(8); // подключиться к i2c шине с адресом #8 Wire.onReceive(receiveEvent); // зарегистрировать обработчик события Serial.begin(9600); // настроить последовательный порт для вывода } void loop() { delay(100); } // функция, которая будет выполняться всякий раз, когда от мастера принимаются данные // данная функция регистрируется как обработчик события, смотрите setup() void receiveEvent(int howMany) { while (1 < Wire.available()) // пройтись по всем до последнего { char c = Wire.read(); // принять байт как символ Serial.print(c); // напечатать символ } int x = Wire.read(); // принять байт как целое число Serial.println(x); // напечатать число }

    Wire.onRequest()

    Описание

    Регистрирует функцию, которая будет вызываться, когда мастер запрашивает данные от ведомого устройства.

    Синтаксис

    Wire.onRequest(handler)

    Параметры

    handler: функция, которая должна будет вызываться, она не принимает параметров и ничего не возвращает, т.е.:

    void myHandler()

    Возвращаемое значение

    Пример

    Код для платы Arduino, работающей в качестве ведомого устройства:

    #include void setup() { Wire.begin(8); // подключиться к i2c шине с адресом #8 Wire.onRequest(requestEvent); // зарегистрировать обработчик события } void loop() { delay(100); } // функция, которая будет выполняться всякий раз, когда мастером будут // запрошены данные // данная функция регистрируется как обработчик события, смотрите setup() void requestEvent() { Wire.write("hello "); // ответить сообщением }

    Как расширить функциональность разрабатываемой системы на основе микроконтроллера? Да, этот вопрос интересует многих схемотехников, работающими над прототипами электронных устройств. Удивительно, но добавить к системе новые блоки, не изменяя схемы, позволит шина, разработанная инженерами Philips более 30 лет назад.

    Благодаря интерфейсу I2C можно превратить микроконтроллер в простой конструктор, к которому можно подключить несколько сотен микросхем. Сразу стоит отметить, что их количество ограничивается емкостью шины в 400 пФ, но это один из немногих недостатков I2C.

    Схема внутренней связи – так можно расшифровать название шины, которую сегодня можно встретить практически в каждом электронном устройстве. Стоит отметить, что в Philips запатентовали столь удачное в практическом плане решение и другие производители дублировали I2C под другими названиями.

    Именно эта шина устанавливается для связи с внешним миром дисплеев, камер, сотовых телефонов. Количество периферических устройств, подключаемых к устройствам с помощью I2C, вообще не поддается учету. В чем же преимущества интерфейса?

    Основные достоинства и недостатки I2C

    I2C – последовательная асимметричная шина для связи между интегральными схемами внутри электронных приборов. Использует две двунаправленные линии связи (SDA и SCL).

    Шина представляет собой два проводника, а для управления интерфейсом достаточно одного микроконтроллера. Удивительно, но подобная простота позволяет производить отключение микросхем в процессе работы. Специальный встроенный фильтр способен справляться с всплесками, гарантируя сохранность обрабатываемой информации.

    Среди недостатков I2C, кроме ограниченной емкости, сложность программирования и трудность с определением неисправности в ситуации с состоянием низкого уровня.

    Изначально скорость шины была всего 100 кбит, а подключить к ней было можно всего 120 устройств. В 90-х годах стандарты изменились и скорость передачи данных увеличилась в 4 раза и появилась возможность подключения до 1000 микросхем.

    Однако большинство производителей интерфейса зациклились на 400 кбит с подключением 120 устройств.

    Принцип подключения и работы

    Проводники шины подсоединены к плюсу резисторами 1-10к, один из проводников является шиной данных, другой – тактирование. Работает такая схема просто: на линии есть одно ведущее устройство (микроконтроллер) и несколько периферийных устройств. Так как линии запитаны на плюсе, то подключенному слейву (ведомому элементу) достаточно прижать провод к земле и передать тем самым 0.

    Когда периферическое устройство отпускает провод, по проводнику передается 1. Все элементарно, но если при совместной работе один из слейвов выдал 0, то остальным подключенным к шине устройствам придется подождать. Осуществляет тактирование и передачу микроконтроллер, предварительно уточнив, свободна ли линия. Для этого передается 1 на SCL и SDA, после чего создается старт-условие – прижимается линия SDA при значении SCL равном 1.

    Следующим этапом работы является передача адреса того устройства, к которому нужно обратиться.

    При этом нужно помнить, что считывание данных осуществляется при SCL =1, а передача идет вперед старшим битом.

    Первые 7 бит – адрес устройства, 8 – команда записать (0) или читать (1).

    Слейв получит все восемь сигналов, прижмет линию SDA на девятом такте SCL если ему все понятно. Если нет – то формируется сигнал стоп и передача данных осуществляется снова. При завершении работы отпускается линия SDA, при этом SCL не трогают.

    Даже в том случае, если подключенная микросхема медленно обрабатывает сигнал, все равно она придержит SCL.

    Режим работы multi-master

    Вопросы демократии в схемотехнике регламентируются . В его основе лежит способность ведущего устройства контролировать результат работы. Обязательно перепроверяется – отпущена линия или нет, если она отпустилась – то мастер на данный момент ведущий, если нет – то что-то более важное пока держит линию. В этом случае нужно подождать просвет и сделать свою работу, когда таковой появится.

    Однако, вполне возможно что все ведущие устройства решать заняться делом одновременно. В этом случае первенство будет за тем мастером, который первым начал тактирование и сделал это быстро. Если два устройства будут работать сверхсинхронно, то первым победит то из них, которое сгенерирует 0 чуть быстрее оппонента.