I²C - Inter-Integrated Circuit, краткое руководсто

  • Данная статья является кратким дискурсом по шине I²C и не должна восприниматься как точная техническая документация. Более подробно ознакомится с работой шины Вы можете в официальной документации на сайте компании NXP.

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

I²C (и-квадрат-це, ай-ту-си, ай-сквэрд-си), Inter-Integrated Circuit - последовательная шина обмена данными между интегральными схемами. Изобретена и в начале 80-х компанией Philips Semiconductor (теперь NXP), передача данных осуществляется по двум проводам в обе стороны. Ведущий и ведомый могут выполнять как роль приёмника, так и передатчика. Для возможности соединения более двух устройств используются адресация. Опрашивать адреса шины может только ведущий. Адрес последовательно выводится на линию SDA сразу после сигнала Start. В этой статье речь пойдёт только о 7-ми битной адресации, так же не будет затронута тема нескольких ведущих. На каждом устройстве, поддерживающем I²C обычно обозначены два вывода: SDA и SCL. SDA (serial data) - означает последовательные данные, SCL (serial clock) - последовательное тактирование. Эти выводы являются выводами открытого коллектора или открытого стока, это означает что ведущий и ведомый могут только притягивать электрический потенциал к земле, поэтому на каждой линии должны быть подтягивающие резисторы. Сопротивление резисторов рассчитывается в зависимости от паразитной ёмкости линии.

Подключение:

Шина поддерживает подключение до 112 устройств (при 7-ми битной адресации) по двум проводам (плюс GND и Vcc), может иметь несколько ведущих и ведомых. При использовании нескольких ведущих, каждый из них должен поддерживать этот режим и уметь определять состояние занятой шины.

I²C на Arduino

Arduino UNO R3/Piranha UNO

На Arduino UNO R3/Piranha UNO шина I2C находится на выводах A4, A5. Также в эти выводы продублированы на колодке с цифровыми выводами рядом с кнопкой Reset.

Piranha ULTRA

На Piranha ULTRA шина I²C не занимает аналоговые выводы A4, A5 и находится на цифровой колодке рядом с кнопкой Reset, выводы обозначены SDA и SCL

Arduino MEGA R3

На Arduino MEGA R3 шина I²C находится на цифровой колодке на крайних выводах, близких к разъёму USB и на выводах 20, 21. Выводы объединены.

Примеры для Arduino

Работа с шиной с использованием встроенной библиотеки Wire Arduino IDE на примере  Trema-модуля LED Матрицы 8x8 - i2c

#include <Wire.h>                                // Подключаем библиотеку Wire для работы с шиной I2C.
const int ADDRESS    =  0x09;                    // Определяем адрес ведомого
const int REG_DATA   =  0x10;                    // Определяем адрес регистра REG_DATA.
const int REG_ROW_1  =  0x11;                    // Определяем адрес регистра ROW_1.
byte      IMAGE[8]   = {0b00000000,              // Определяем массив из 8 байт.
                        0b00011000,              // где каждый байт массива это строка изображения,
                        0b00111100,              // а каждый бит байта управляет одним светодиодом.
                        0b01111110,              // 
                        0b00011000,              // Если бит установлен то светодиод включён.
                        0b00011000,              // 
                        0b00011000,              // В данном примере массив содержит изображение стрелки направленной вверх.
                        0b00000000};             //
void setup(){                                    //
    Wire.setClock(100000L);                      // Устанавливаем скорость передачи данных по шине I2C.
    Wire.begin();                                // Инициируем работу c шиной I2C в качестве мастера.
    delay(500);                                  //
    Wire.beginTransmission(ADDRESS);             // Инициируем передачу данных по шине I2C к устройству с адресом ADDRESS и битом RW=0 (запись). При этом сама передача не начнётся.
    Wire.write(REG_ROW_1);                       // Функция write() помещает значение своего аргумента в буфер для передачи. В данном случае это номер регистра ROW_1.
    Wire.write(IMAGE, 8 );                       // Функция write() помещает значение своего аргумента в буфер для передачи. В данном случае это 8 байт массива IMAGE.
    Wire.endTransmission();                      // Выполняем инициированную ранее передачу данных.
}                                                //
                                                 //
void loop(){                                     // 
    //
}

В этом примере на матрицу выводится изображение стрелки. Стоит заметить, ко всем нашим модулям написаны библиотеки с высокоуровневым интерфейсом и вовсе не обязательно работать с матрицей на низком уровне. Подробнее о работе с библиотекой матрицы можно узнать по этой ссылке.

I²C на Raspberry Pi

На Raspberry Pi I²C выводы это 3-й и 5-й выводы колодки, GPIO2 и GPIO3 по номенклатуре BCM и выводы 8, 9 по номенклатуре WiringPi.

Примеры для Raspberry

Работа с шиной с использованием модуля smbus для Python на примере Trema-модуля Матрицы 8x8 - i2c. Для работы с шиной её необходимо включить в настройках Raspberry при помощи утилиты raspi-config. Ссылка на подробное описание как это сделать.

# Импортируем модуль Python
import smbus

# Создаём объект для работы с шиной
# 0: "/dev/i2c-0", 1: "/dev/i2c-1"
bus = smbus.SMBus(1)

# Адрес ведомого на шине
ADDRESS = 0x09;

# Регистр первого ряда светодиодов матрицы
REG_ROW_1 = 0x11;

# Список с изображением стрелки в двоичной записи
IMAGE = [
          0b00000000,
          0b00011000,
          0b00111100,
          0b01111110,
          0b00011000,
          0b00011000,
          0b00011000,
          0b00000000,
        ]

# Команда вывода данных на шину.
bus.write_i2c_block_data(ADDRESS, REG_ROW_1, IMAGE)

Так же как и в примере с Arduino, в этом примере на матрицу выводится изображение стрелки. Стоит заметить, к Trema-модулю LED Матрица 8x8 - i2c написана библиотека с высокоуровневым интерфейсом и вовсе не обязательно работать с матрицей на низком уровне. Подробнее о работе с библиотекой матрицы можно узнать по этой ссылке

Подробнее о шине I²C:

Резисторы, ёмкость и длина линий шины

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

При использовании шины на модулях не существует принятого стандарта установки подтягивающих резисторов на ведущем или ведомом. У Arduino подтягивающие резисторы отсутствуют и для работы с шиной нужен хотя бы один модуль с ними. У Raspberry Pi на плате установлены подтягивающие резисторы номиналом 1,7 килоОм и для неё нет необходимости в подтяжке на модулях.

Сигналы и специальные биты шины

В состоянии покоя линии шины находятся на верхнем потенциале (обычно 3,3 В или 5 В, но могут быть и другие напряжения). Бездействие устройства, по умолчанию, воспринимается как логическая 1. Для простоты понимания можно рассмотреть аналогию: Вообразим верхний потенциал как уровень воды, а нижний как дно. Представьте, что Вы на рыбалке - попловок в состоянии покоя остаётся на поверхности, когда клюёт - идёт ко дну. Так же и в здесь, при обмене данными линии прижимаются в нулевому потециалу. Далее рассмотрим поочереди сингалы и специальные биты.

Устанавливаемые только ведущим

  • Start - сигнал начала обмена данными. Линия тактирования SCL отпущена (логическая 1), ведущий пижимает линию данных SDA (переход из логической 1 в логический 0). После этого обмен данными происходит побайтово. Первый байт - семь бит адреса ведомого и бит направления (запись или чтение). Последующие байты - данные. после этого сигнала шина считается занятой.

Краткое обозначание сигнала  S - заглавная буква S латинского алфавита.

SDA (данные)      S, биты: 1     2     3     4     5     6     7    R/W̅
___________________      _____ _____ _____ _____ _____ _____ _____ _____         ___
                   \____/_____X_____X_____X_____X_____X_____X_____X_____\_______/ 
SCL (такт.)        | 
______________________    __    __    __    __    __    __    __    __    __    ____
                   |  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/
                   |       
                   Start: переход SDA из 1 в 0,            
                     линия SCL отпущена

  • Бит Read - Если ведущий желает получить данные, он устанавливает логическую 1 сразу после адреса, информируя ведомого о том, что данные будут считываться (управление линией данных передаётся ведомому). 

Краткое обозначание R - заглавная буква R латинского алфавита.

SDA (данные)      S, биты: 1     2     2     4     5     6     7    R
___________________      _____ _____ _____ _____ _____ _____ _____ _____         ___
                   \____/_____X_____X_____X_____X_____X_____X_____/ |   \_______/
SCL (такт.)                                                         |              
______________________    __    __    __    __    __    __    __    __    __    ____
                      \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/| \__/  \__/ 
                                                                    |              
                                                       Read: после 7-бит адреса            
                                                         линия SDA отпущена

  • Бит Write - Если ведущий желает записать данные, он устанавливает логический 0 сразу после адреса для информирования ведомого о том что данные будут записываться (управление линией данных остаётся у ведущего). 

Краткое обозначение - заглавная буква W латинского алфавита с чертой сверху.

SDA (данные)      S, биты: 1     2     3     4     5     6     7    W̅
___________________      _____ _____ _____ _____ _____ _____ _____               ___
                   \____/_____X_____X_____X_____X_____X_____X_____\_____________/
SCL (такт.)                                                         |              
______________________    __    __    __    __    __    __    __    __    __    ____
                      \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/| \__/  \__/ 
                                                                    |              
                                                       Write: после 7-бит адреса            
                                                         линия SDA прижата


  • Stop - сигнал окончания обмена данными. Ведущий прекращат тактирование, линия тактирования SCL отпущена (логическая 1), линия данных SDA переведена ведущим из логического 0 в логическую 1. После этого сигнала шина считается свободной.

Краткое обозначение P - заглавная буква P латинского алфавита.

SDA (данные)          A   .........байт.данных.........................   A     P
_ _____ _____ _____      _____ _____ _____ _____ _____ _____ _____ _____         ___
_X_____X_____X_____\____/_____X_____X_____X_____X_____X_____X_____X_____\_______/
SCL (такт.)                                                                     |  
  __    __    __    __    __    __    __    __    __    __    __    __    __    ____
_/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/|
                                                                                |  
                                                         Stop: переход SDA из 0 в 1,            
                                                         линия SCL отпущена


  • Restart - сигнал продолжения обмена данными (используется взамен сигналу Stop с последующим Start для продолжения опрашивания шины). Используется в основном при наличии нескольких ведущих на шине, чтобы управление не перешло другому ведущему после сигнала Stop. Линия тактирования SCL отпущена ведущим, линия данных SDA  переведена ведущим из логической 1 в логический 0. 

Обозначается Sr - заглавная буква S и строчная буква r латинского алфавита.

SDA (данные)         A    ...............биты данных...................   A      Sr
_ _____ _____ _____      _____ _____ _____ _____ _____ _____ _____ _____       __
_X_____X_____X_____\____/_____X_____X_____X_____X_____X_____X_____X_____\_____/  \__
SCL (такт.)                                                                      |  
  __    __    __    __    __    __    __    __    __    __    __    __    __    ____
_/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/ |
                                                                                 |  
                                                       Restart: переход SDA из 1 в 0,            
                                                         линия SCL отпущена

Устанавливаемые ведущим и ведомым

Данные биты может устанавливат как ведущий, так и ведомый. В такой ситуации устанавливающее устройство или модуль (ведущий или ведомый) называют передатчиком, а считывающее устройство - приёмником.

  • Бит ACK - (сокращ. англ. acknowledged - подтверждено) каждый девятый импульс тактирования передатчик (ведущий или ведомый) отпускает линию данных. Если линия была прижата приёмником (логический 0) - принятые данные верны, передача может быть продолжена или закончена. 

Обозначается A - заглавная буква A латинского алфавита

SDA (данные)         A    ..................биты данных................   A   
_ _____ _____ _____      _____ _____ _____ _____ _____ _____ _____ _____       __
_X_____X_____X_____\____/_____X_____X_____X_____X_____X_____X_____X_____\_____/  \__
SCL (такт.)          |                                                    |        
  __    __    __    __    __    __    __    __    __    __    __    __    __    ____
_/  \__/  \__/  \__/ |\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/| \__/ 
                     |                                                    |         
              ACK: девятый импульс тактирования --------------------------^
              линия SDA прижата ведомым (логический 0)

  • Бит NACK - (сокращ. англ. not acknowledged - не подтверждено) каждый девятый импульс тактирования передатчик (ведущий или ведомый) отпускает линию данных. Если линия была отпущена принимающим или принимающего нет на шине (логическая 1) - принятые данные неверны, произошла ошибка, передача не может быть продолжена. Обозначается A̅ - заглавная буква A латинского алфавита с чертой сверху.
SDA (данные)      S      ...........биты данных или адреса.............   A̅        S
___________________      _____ _____ _____ _____ _____ _____ _____ _____ ____      _
                   \____/_____X_____X_____X_____X_____X_____X_____X_____/ |  \____/
SCL (такт.)                                                               |        
______________________    __    __    __    __    __    __    __    __    __    ____
                      \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/| \__/ 
                                                                          |        
                                          NACK: девятый импульс тактирования
                                            линия SDA отпущена принимающим (логическая 1)

Обмен данными

При обмене данными тактированием занимается только ведущий, а ведомый может удерживать линию тактирования только если не успевает за ведущим, так называемое растягивание тактирования (clock-stretching). Не все модули поддерживают удержание. Установка бита на линии данных может происходит в момент, когда линия тактирования прижата, а считывания, когда линия отпущена (подтянута к Vcc), но в большинстве случаев это происходит по фронту волны на линии тактирования. 

SDA (данные)
___________________      _____ _____ _____ _____ _____ _____ _____ _____         ___
                   \____/_____X_____X_____X_____X_____X_____X_____X_____\_______/ 
SCL (тактирование)      |  |
______________________  | __    __    __    __    __    __    __    __    __    ____
                      \__/ |\__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/
                        |  |
                        |  |
                        |  Считывание
                        Установка

Рассмотрим пример простого обмена данными:

Запись в регистры ведомого. Данные взяты из примеров, приведённых выше.

S | 0x09 | W̅ | A | 0x11 | A | 0x00 | A |0x18|A|0x3C|A|0x7E|A|0x18|A|0x18|A|0x00|A| P |
 |   |     |   |     |    |    |                                                   |
 | Адрес   | Подтв.  |  Подтв. |    .............................................  |
 |         |         |         |                                                   |
Старт   Запись    Регистр    Данные                                              Стоп

После сигнала Start и указания адреса ведущий записывает адрес регистра с которого будет производиться дальнейшая запись. Стоит заметить, что у ведомого есть внутренний счётчик и каждый последующий байт после подтверждения будет записан в следующий регистр. Таким образом байт со значением 0x00 будет записан в регистр 0x11, байт со значением 0x18 будет записан в регистр 0x12, байт со значением 0x3C будет записан в регистр 0x13 и т. д. В этом примере биты ACK устанавливает ведомый.

Вот так сигналы этого примера выглядят на осциллографе:

  • Канал 1 - тактирование (SCL)
  • Канал 3 - данные (SDA)
  • Линия B1 - декодирование данных осциллографом

Чтение из регистров ведомого. Предположим, мы хотим прочитать байт из регистра 0x13.

 S | 0x09 | W̅ | A | 0x13 | Sr | 0x09 | R | A | 0x3C | A | P
 |    |     |   |    |      |    |     |   |    |     |   |
 |  Адрес   | Подтв. |   Рестарт |  Чтение |  Данные  |  Стоп
 |          |        |           |         |          |
Старт    Запись   Регистр      Адрес     Подтв.    Подтв. ведущим

После сигнала Start и указания адреса ведущий записывает адрес регистра, который необходимо прочитать. Далее следует сигнал Restart (или Stop, затем Start). Ведущий снова выводит адрес ведомого, но уже с битом Read (чтения). Ведомый устанавливает бит ACK и во время следующих 8-ти импульсов тактирования выводит данные на линию SDA. На девятом импульсе уже ведущий устанавливает бит ACK (или NACK, если данные не удалось прочитать) и завершает обмен сигналом Stop.

Скорость

Первоначальный стандарт I²C был реализован на скорости 100 кГц. С тех пор появились и другие реализации шины, но большинство устройств работают на этой скорости. Так же известны случаи когда скорость шины специально снижена, чтобы увеличить расстояние передачи и уменьшить чувствительность к помехам. Не все модули могут работать на сниженной скорости.

Ссылки

Обсуждение