I2c communication protocol basics

ADDRESSING

Addressing in the I2C protocol is fundamental, identifying and selecting devices for data communication. It establishes connections between master and slave devices, enabling data exchange. I2C addressing employs 7-bit or 10-bit device addresses. A 7-bit address offers 128 unique device addresses, while a 10-bit address extends to 1024. These distinctions are crucial when multiple devices share the same I2C bus.

In I2C, the master starts communication with a transmitted Start condition and the 7-bit device address of the target slave. This unique address ensures accurate recipient selection, trigger on oscilloscope, with the MSB sent first, followed by the remaining six bits, i2c seven segment display. Address transmission in I2C also sets the Read/Write bit, indicating data flow. ‘0’ means write (master to slave), while ‘1’ means read (master receives from slave).

After sending the address byte, the addressed device acknowledges by pulling SDA low for one clock cycle. No acknowledgment may suggest device absence or unresponsiveness, requiring troubleshooting.

Steps of I2C Data Transmission

1. The master sends the start condition to every connected slave by switching the SDA line from a high voltage level to a low voltage level before switching the SCL line from high to low:

2. The master sends each slave the 7 or 10 bit address of the slave it wants to communicate with, along with the read/write bit:

3. Each slave compares the address sent from the master to its own address. If the address matches, the slave returns an ACK bit by pulling the SDA line low for one bit. If the address from the master does not match the slave’s own address, the slave leaves the SDA line high.

4. The master sends or receives the data frame:

5. After each data frame has been transferred, the receiving device returns another ACK bit to the sender to acknowledge successful receipt of the frame:

6. To stop the data transmission, the master sends a stop condition to the slave by switching SCL high before switching SDA high:

Функции I2C в Arduino

Для того, что бы использовать интерфейс I2C в arduino, необходимо подключить библиотеку Wire.h. Эта библиотека содержит все функции по инициализации, приему и передаче данных по шине.

Wire.write(data)

Данная функция используется для записи (передачи) данных на ведущее или ведомое устройство.

Параметр

data
это однобайтовое значение, строка, массив данных.

Возвращает

Количество записанных байтов

Пример

Wire.write(7); // отправляем байт данных
Wire.write("i2c"); //отправляем строку на ведомое устройство
Wire.write(a, 6); // здесь а массив
Wire.available()

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

Wire.read()

Данная функция предназначена для чтения данных, запрошенных мастером с ведомого, или чтения данных, переданных от ведущего к мастеру.

Примечание

Каждое ведомое устройство I2C имеет уникальный адрес. Во время обмена данными этот адрес подчиненного устройства необходимо использовать мастером для инициализации обмена.

Wire.begin ()

Функция инициализирует библиотеку Wire.h и подключает устройство к шине I2C в качестве мастера.

Wire.beginTransmission(slave address)

Эта функция начинает передачу с ведомого устройства I2C, имеющего свой уникальный адрес.

Параметр

slave address
7-битный адрес устройства, с которым мы хотим установить связь

Пример

Wire.beginTransmission (50) //начать передачу с ведомого устройства с адресом 50.
Wire.requestFrom(address, quantity)

ИЛИ

Wire.requestFrom(address, quantity, stop)

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

Wire.read()

Параметры

address
адрес устройства, с которым мы хотим общаться
quantity
количество запрашиваемых байт
stop
значение true или false. true — отправлять стоп-сообщение после запроса, освобождая шину. false — постоянно отправлять перезагрузку после запроса, сохраняя соединение активным

Возвращает

Число байт, возвращенных ведомым устройством

Пример

Wire.requestFrom(50, 4)           // запрос 4-х байт от ведомого устройства с адресом 50
Wire.requestFrom(50, 4, true) //перестанет получать данные после 4 байт, освобождая  шину.
Wire.endTransmission()

Функция завершает передачу на ведомое устройство, начатую функцией

beginTransmission()

, и передает байты, поставленные в очередь функцией

write()

Возвращает

Байт, который указывает статус передачи.

Wire.begin(address)

Функция инициирует библиотеку Wire и подключается к шине I2C в качестве подчиненного устройства с указанным адресом.

Параметр

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

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

Пример

void setup() {
  Wire.begin(8);                //инициализируем I2C шину с адресов #8
  Wire.onReceive(receiveEvent); // регистрируем событие обработчика
  Serial.begin(9600);           // инициализируем UART
}
void receiveEvent (int howmany){
  while (1 < Wire.available()) { // в цикле проверяем поступили ли на шину I2C данные
    char c = Wire.read();        // если да, читаем байт
       Serial.print(c);             // отправляем его на UART
  }
}    
Wire.onRequest(handler)

Функция-обработчик, которая вызывается, когда мастер запрашивает у ведомого устройства, не принимает параметров и ничего не возвращает.

Пример

void setup() {
  Wire.begin(8);                //инициализируем I2C шину с адресов #8
  Wire.onRequest(requestEvent); // регестрируем событие 
}
void loop() {
  delay(100);
}

// функция, которая выполняется всякий раз, когда мастер запрашивает данные
// эта функция регистрируется как событие
void requestEvent() {
  Wire.write("hello "); // оправляем сообщение 6 байт
  // как и ожидал мастер
}

Beagle I2C/SPI Protocol Analyzer + Data Center

Программное обеспечение Total Phase Data Center для работы с Beagle Protocol Analyzer

Beagle Protocol Analyzer — устройство, разработанное компанией Total Phase для захвата и анализа данных, передаваемых по шинам SPI и I2C. Подключается к компьютеру через USB, требует для работы специальный драйвер и ПО Data Center.

Анализатор способен считывать данные с линии I2C при частоте шины до 4 МГц, работает только в режиме чтения данных.

Total Phase Data Center — ПО, написанное для работы с серией анализаторов аппаратных интерфейсов (SPI, I2C, USB, CAN), разработанных компанией Total Phase. Для этой серии анализаторов также официально распространяется API для написания собственных программ.

Считанные данные отображаются в окне несколькими способами: в сыром виде (raw) и в виде списка транзакций (сохраняющим, в том числе, время начала передачи). Умеет сохранять записи транзакций, а также экспортировать полученные данные в виде CSV для последующей обработки любым удобным способом, в том числе в математических средах (таких как Matlab) или электронных таблицах.

Как выбрать номинал подтягивающих резисторов

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

Это приводит к важному вопросу: «Какой выбрать номинал для подтягивающего резистора?». Компромисс между скоростью и рассеиваемой мощностью: более низкое сопротивление уменьшает постоянную времени RC цепи, но увеличивает величину тока, протекающего от VDD на землю (через подтягивающий резистор), когда на SCL или SDA выставлен низкий логический уровень

Официальная спецификация I2C (стр. 9) гласит, что напряжение не считается «логическим высоким уровнем», пока не достигнет 70% от VDD. Вы можете вспомнить, что постоянная времени RC цепи говорит нам, сколько времени потребуется, чтобы напряжение достигло примерно 63% от конечного напряжения. Таким образом, для простоты будем считать, что R×C говорит нам, сколько времени потребуется, чтобы уровень сигнала вырос от напряжения, близкого к потенциалу земли, до уровня логической единицы.

Теперь, как найти емкость? «Простой» способ – это сборка всей системы и измерение емкости; по крайней мере, это, вероятно, проще, чем пытаться выполнить точный расчет, который учитывает каждый источник емкости – как отмечает рекомендация от Texas Instruments, «при обычном построении электрических схем формируется невообразимое количество конденсаторов». Если подход с измерением не подходит (как это часто бывает), вы можете выполнить приблизительную оценку, определив емкость вывода для каждого устройства на шине (здесь вам поможет техническое описание), а затем добавить 3 пФ на дюйм дорожки на печатной плате и 30 пФ на фут коаксиального кабеля (эти цифры взяты из той же рекомендации, стр. 3).

Предположим, что у нас емкость шины составляет 50 пФ, и мы хотим соответствовать спецификации «стандартного режима» I2C, в которой указано, что максимальное время нарастания составляет 1000 нс.

\

Таким образом, можно соответствовать требованиям спецификации с Rподтягивающий = 20 кОм: это значение также дает минимальное энергопотребление. Как насчет скорости? Предположим, вы хотите, чтобы длительность присутствия высокого логического уровня на линии синхронизации было, по крайней мере, в три раза больше времени нарастания.

\

Если 167 кГц не достаточно много, вы можете снизить сопротивление (за счет увеличения энергопотребления), пока не достигните желаемой тактовой частоты. (Фактически, «стандартный режим» ограничивает тактовую частоту до 100 кГц, но вы можете адаптировать эти спецификации под потребности вашей системы.)

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

Примеры устройств, использующих i2C

Шина i2C широко используется во множестве различных устройств, таких как:

  1. Датчики температуры: многие датчики температуры подключаются к микроконтроллерам и другим устройствам через i2C. Например, датчики температуры для регулирования температуры в системах отопления или кондиционирования воздуха.
  2. Датчики влажности: многие датчики влажности также подключаются к устройствам через i2C. Эти датчики используются, например, для контроля и регулирования влажности в теплицах или системах автоматического полива.
  3. Датчики освещенности: датчики освещенности, такие как фоторезисторы или цифровые датчики освещенности, могут быть подключены к микроконтроллеру или другим устройствам через i2C для получения данных о текущем уровне освещенности.
  4. Экраны и дисплеи: многие LCD-дисплеи и другие виды экранных устройств могут быть подключены к микроконтроллерам через i2C для вывода информации или отображения данных.
  5. Акселерометры и гироскопы: акселерометры и гироскопы, используемые в навигационных и управляющих системах, могут быть подключены к микроконтроллерам через i2C для получения данных о движении и ориентации объекта.
  6. Датчики давления: датчики давления используются во многих приложениях, таких как измерение атмосферного давления или измерение давления внутри устройств. Они могут быть подключены к микроконтроллерам через i2C для получения данных.

Это лишь несколько примеров устройств, которые могут использовать i2C в своей работе. Шина i2C широко распространена и применяется во многих других устройствах, позволяя им взаимодействовать и обмениваться данными с другими устройствами.

I2C Applications

I2C is a widely used protocol in a variety of applications, including:

Embedded systems: I2C is commonly used in embedded systems to communicate with sensors, displays, and other peripherals. Its simplicity and low power consumption make it an ideal choice for these types of applications.

Industrial automation: I2C is used in industrial automation systems to connect sensors, actuators, and other devices to control and monitor processes.

Consumer electronics: I2C is used in a range of consumer electronics devices, such as smartphones, tablets, and laptops, to communicate with sensors, displays, and other peripherals.

Medical devices: I2C is used in medical devices such as monitoring systems, glucose meters, and portable oxygen concentrators to communicate with sensors and other peripherals.

Automotive: I2C is used in automotive systems to communicate with sensors, displays, and other peripherals, such as in engine control systems, infotainment systems, and safety systems.

Aerospace: I2C is used in aerospace applications to communicate with sensors, displays, and other peripherals, such as in aircraft avionics systems and satellite communication systems.

История создания и особенности протокола

Протокол I2C (Inter-Integrated Circuit) был разработан компанией Philips (в настоящее время NXP Semiconductors) в 1982 году. Этот протокол был разработан для обеспечения коммуникации между различными микросхемами внутри одного устройства. I2C стал широко распространенным и применяется во многих электронных устройствах, таких как компьютеры, смартфоны, телевизоры, автомобильная электроника и др.

I2C является двухпроводным серийным протоколом связи, который использует только две линии для передачи данных: линию данных (SDA) и линию тактирования (SCL). Линия данных используется для передачи информации, а линия тактирования используется для синхронизации передачи данных между устройствами.

I2C имеет несколько особенностей, которые делают его удобным для использования:

  • Многочисленные устройства могут быть подключены к одной шине I2C, что позволяет экономить пинов микроконтроллера или другого микросхемного устройства.
  • Устройства могут работать в режиме ведущего (мастера) или в режиме ведомого (слейва). В режиме ведущего мастер управляет передачей данных, а в режиме ведомого слейв принимает передаваемую информацию.
  • I2C поддерживает различные скорости передачи данных, включая стандартные скорости 100 кбит/с и 400 кбит/с, а также скорость High-Speed режима до 3.4 Мбит/с.
  • Протокол I2C поддерживает передачу данных как в формате байтов (8 бит), так и в формате слов (16 бит), что позволяет передавать большие блоки данных.
  • I2C протокол имеет встроенные механизмы контроля ошибок, такие как контрольная сумма и повторная передача данных, что повышает надежность передачи информации.

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

Применение функции i2c в различных областях

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

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

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

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

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

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

Главные преимущества I2C включают низкую сложность подключения и небольшое количество проводов, что делает его идеальным вариантом для связи с различными устройствами на микроконтроллерной плате, такими как датчики, актуаторы и OLED-дисплеи.

Основная идея I2C заключается в том, что микроконтроллер может быть настроен как мастер или слейв устройство. Мастер контролирует передачу данных, генерируя тактовый сигнал на линии SCL, в то время как слейв устройства получают и обрабатывают данные, посылаемые по линии SDA.

I2C также предлагает несколько способов коммуникации, включая чтение и запись данных, отправку и прием сигналов ACK/NACK (подтверждение/отказ) и отправку команд. Это позволяет гибко управлять данными, обмен производится пакетами информации со структурированными заголовками и контрольными битами для обнаружения ошибок.

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

Преимущества Ограничения
Простота подключения и использования Малая длина проводов
Малое количество проводов Недостаточная скорость передачи данных для некоторых приложений
Гибкое управление данными Конечное количество адресов устройств

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

Объяснение программы для ведомой (Slave) платы Arduino

1. Как и в ведущей плате, первым делом в программе мы должны подключить библиотеку Wire для задействования возможностей протокола I2C и библиотеку для работы с ЖК дисплеем. Также нам необходимо сообщить плате Arduino к каким ее контактам подключен ЖК дисплей.

Arduino

#include<Wire.h>
#include<LiquidCrystal.h>
LiquidCrystal lcd(2, 7, 8, 9, 10, 11);

1
2
3

#include<Wire.h>    
#include<LiquidCrystal.h>      

LiquidCrystallcd(2,7,8,9,10,11);

  1. В функции void setup():

—  мы инициализируем последовательную связь со скоростью 9600 бод/с;

Arduino

Serial.begin(9600);

1 Serial.begin(9600);

— далее мы инициализируем связь по протоколу I2C на контактах A4 и A5

В качестве адреса ведомого мы будем использовать значение 8 – очень важно здесь указать адрес ведомого;. Arduino

Wire.begin(8);

Arduino

Wire.begin(8);

1 Wire.begin(8);

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

Arduino

Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);

1
2

Wire.onReceive(receiveEvent);

Wire.onRequest(requestEvent);

— затем мы инициализируем ЖК дисплей для работы в режиме 16х2, отображаем на нем приветственное сообщение и очищаем его экран через 5 секунд.

Arduino

lcd.begin(16,2); //Initilize LCD display
lcd.setCursor(0,0); //Sets Cursor at first line of Display
lcd.print(«Circuit Digest»); //Prints CIRCUIT DIGEST in LCD
lcd.setCursor(0,1); //Sets Cursor at second line of Display
lcd.print(«I2C 2 ARDUINO»); //Prints I2C ARDUINO in LCD
delay(5000); //Delay for 5 seconds
lcd.clear(); //Clears LCD display

1
2
3
4
5
6
7

lcd.begin(16,2);//Initilize LCD display

lcd.setCursor(,);//Sets Cursor at first line of Display

lcd.print(«Circuit Digest»);//Prints CIRCUIT DIGEST in LCD

lcd.setCursor(,1);//Sets Cursor at second line of Display

lcd.print(«I2C 2 ARDUINO»);//Prints I2C ARDUINO in LCD

delay(5000);//Delay for 5 seconds

lcd.clear();//Clears LCD display

3. Затем нам будут необходимы две функции: одна для события запроса (request event) и одна для события приема (receive event).

Для события запроса:

Эта функция будет выполняться когда ведущий будет запрашивать значение от ведомого. Эта функция будет считывать значение с потенциометра, подключенного к ведомой плате Arduino, преобразовывать его в диапазон 0-127 и затем передавать его ведущей плате.

Arduino

void requestEvent()
{
int potvalue = analogRead(A0);
byte SlaveSend = map(potvalue,0,1023,0,127);
Wire.write(SlaveSend);
}

1
2
3
4
5
6

voidrequestEvent()

{

intpotvalue=analogRead(A0);

byteSlaveSend=map(potvalue,,1023,,127);

Wire.write(SlaveSend);

}

Для события приема:

Эта функция будет выполняться когда ведущий будет передавать данные ведомому с адресом 8. Эта функция считывает принятые значения от ведущего и сохраняет ее в переменной типа byte.

Arduino

void receiveEvent (int howMany)
{
SlaveReceived = Wire.read();
}

1
2
3
4

voidreceiveEvent(inthowMany)

{

SlaveReceived=Wire.read();

}

4. В функции Void loop():

Мы будем непрерывно отображать принятые от ведущей платы значения на экране ЖК дисплея.

Arduino

void loop(void)
{
lcd.setCursor(0,0); //Sets Currsor at line one of LCD
lcd.print(«>> Slave <<«); //Prints >> Slave << at LCD
lcd.setCursor(0,1); //Sets Cursor at line two of LCD
lcd.print(«MasterVal:»); //Prints MasterVal: in LCD
lcd.print(SlaveReceived); //Prints SlaveReceived value in LCD received from Master
Serial.println(«Slave Received From Master:»); //Prints in Serial Monitor
Serial.println(SlaveReceived);
delay(500);
lcd.clear();
}

1
2
3
4
5
6
7
8
9
10
11
12

voidloop(void)

{

lcd.setCursor(,);//Sets Currsor at line one of LCD

lcd.print(«>>  Slave  <<«);//Prints >> Slave << at LCD

lcd.setCursor(,1);//Sets Cursor at line two of LCD

lcd.print(«MasterVal:»);//Prints MasterVal: in LCD

lcd.print(SlaveReceived);//Prints SlaveReceived value in LCD received from Master

Serial.println(«Slave Received From Master:»);//Prints in Serial Monitor

Serial.println(SlaveReceived);

delay(500);

lcd.clear();

}

После того как вы соберете всю схему проекта и загрузите обе программы в платы Arduino вы можете приступать к тестированию работы проекта. Вращая потенциометр на одной стороне вы должны увидеть изменяющиеся значения на экране ЖК дисплея на другой стороне.

Теперь, когда вы разобрались, как работать с интерфейсом I2C в плате Arduino, вы можете использовать описанные в данной статье приемы для подключения к плате Arduino любых датчиков, работающих по данному протоколу.

How I2C Works

With I2C, data is transferred in messages. Messages are broken up into frames of data. Each message has an address frame that contains the binary address of the slave, and one or more data frames that contain the data being transmitted. The message also includes start and stop conditions, read/write bits, and ACK/NACK bits between each data frame:

Start Condition: The SDA line switches from a high voltage level to a low voltage level before the SCL line switches from high to low.

Stop Condition: The SDA line switches from a low voltage level to a high voltage level after the SCL line switches from low to high.

Address Frame: A 7 or 10 bit sequence unique to each slave that identifies the slave when the master wants to talk to it.

Read/Write Bit: A single bit specifying whether the master is sending data to the slave (low voltage level) or requesting data from it (high voltage level).

ACK/NACK Bit: Each frame in a message is followed by an acknowledge/no-acknowledge bit. If an address frame or data frame was successfully received, an ACK bit is returned to the sender from the receiving device.

Addressing

I2C doesn’t have slave select lines like SPI, so it needs another way to let the slave know that data is being sent to it, and not another slave. It does this by addressing. The address frame is always the first frame after the start bit in a new message.

The master sends the address of the slave it wants to communicate with to every slave connected to it. Each slave then compares the address sent from the master to its own address. If the address matches, it sends a low voltage ACK bit back to the master. If the address doesn’t match, the slave does nothing and the SDA line remains high.

Read/Write Bit

The address frame includes a single bit at the end that informs the slave whether the master wants to write data to it or receive data from it. If the master wants to send data to the slave, the read/write bit is a low voltage level. If the master is requesting data from the slave, the bit is a high voltage level.

The Data Frame

After the master detects the ACK bit from the slave, the first data frame is ready to be sent.

The data frame is always 8 bits long, and sent with the most significant bit first. Each data frame is immediately followed by an ACK/NACK bit to verify that the frame has been received successfully. The ACK bit must be received by either the master or the slave (depending on who is sending the data) before the next data frame can be sent.

After all of the data frames have been sent, the master can send a stop condition to the slave to halt the transmission. The stop condition is a voltage transition from low to high on the SDA line after a low to high transition on the SCL line, with the SCL line remaining high.

Понравилась статья? Поделиться с друзьями:
Автоэксперт
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: