DocsTech
/
Интерфейсы
/

~ cd описание интерфейса i2c: принцип работы, протокол и применение

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

Принцип работы I2C

Принцип работы I2C основан на двухпроводной схеме, которая включает в себя:

  1. SDA (Serial Data Line) — линия данных, по которой передаются данные.
  2. SCL (Serial Clock Line) — линия тактовых импульсов, которая синхронизирует передачу данных.

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

"aligncenter size-full">Схема подключения устройств через интерфейс I2C

Рисунок 1. Схема подключения устройств через интерфейс I2C

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

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

Протокол общения I2C

Протокол общения I2C включает несколько этапов:

  1. Стартовый условие (Start condition): Мастер генерирует стартовый сигнал, чтобы уведомить все устройства о начале передачи. Стартовый сигнал начинается с перехода линии данных SDA с высокого на низкое состояние. Через некоторое время(зависит о частоты) SCL опускается с высокого на низкое состояние.
  2. Адресация(ADDR): Мастер отправляет в первые 7 бит адрес подчиненного, к которому он хочет обратиться. 8 битом указывает направление передачи данных (чтение(1) или запись(0)).
  3. Бит подтверждения(ASK): ведомое устройство посылает логическую единицу, называемый битом подтверждения.
  4. Передача данных(DATA): Данные передаются между мастером и слейвом в виде последовательных байтов. Т.е. ведущий передается 8 бит, а ведомый бит подтверждения.
  5. Стоповое условие (Stop condition): Мастер генерирует стоповый сигнал, чтобы завершить передачу. При окончании передачи линия SDA поднимается с низкого на высокое состояние. Через некоторое время(зависит о частоты) SCL повторяет действие за SDA.

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

"aligncenter size-full">Протокол передачи по интерфейсу I2C

Рисунок 2. Протокол передачи по интерфейсу I2C

Особенности построения I2C

  1. Адресация: Каждое устройство на шине I2C имеет уникальный адрес, который используется для идентификации устройств. Адрес может быть 7-битным или 10-битным.
  2. Скорость передачи: Стандартный режим передачи данных — до 100 кбит/с, быстрый режим — до 400 кбит/с, высокоскоростной режим — до 3,4 Мбит/с.
  3. Четкая синхронизация: данные принимаются всегда правильно, потому что есть синхронизация по тактовому сигналу SCL.

Применение I2C

I2C широко используется в различных электронных устройствах, таких как:

Преимущества и недостатки I2C

Преимущества:

Недостатки:

Примеры реализации контроллеров I2C на разных устройствах

Общение 2-х плат Arduino через интерфейс I2C

Вот пример кода для передачи строки «Hello world» по интерфейсу I2C с использованием Arduino. В этом примере одна Arduino будет выступать в роли мастера, а другая – в роли ведомого устройства. В этом примере мастер отправляет строку «Hello world» на ведомое устройство с адресом 9 через шину I2C. Ведомое устройство принимает эти данные и выводит их в монитор порта Arduino IDE через последовательную связь.

Таблица 1. Схема подключения 2-х плат Arduino
Мастер (Arduino #1)Ведомое устройство (Arduino #2)
1SDA (A4)SDA (A4)
2SCL (A5)SCL (A5)
3GNDGND
Мастер (Arduino C/C++ #1):
...
Копировать
#include <Wire.h>

void setup() {
  Wire.begin(); // Инициализация шины I2C как мастер
  Serial.begin(9600); // Инициализация последовательной связи для вывода информации в монитор порта
}

void loop() {
  Wire.beginTransmission(9); // Начало передачи на устройство с адресом 9 (ведомое устройство)
  Wire.write("Hello world"); // Отправка строки "Hello world"
  Wire.endTransmission(); // Завершение передачи
  delay(1000); // Задержка 1 секунда между отправками
}
Ведомое устройство (Arduino C/C++ #2):
...
Копировать
#include <Wire.h>

void setup() {
  Wire.begin(9); // Инициализация шины I2C с адресом 9 (ведомое устройство)
  Wire.onReceive(receiveEvent); // Установка функции-обработчика для приема данных
  Serial.begin(9600); // Инициализация последовательной связи для вывода информации в монитор порта
}

void loop() {
  delay(100); // Небольшая задержка
}

void receiveEvent(int numBytes) {
  while (Wire.available()) { // Пока есть данные для чтения
    char c = Wire.read(); // Чтение символа из шины I2C
    Serial.print(c); // Вывод принятого символа в монитор порта
  }
  Serial.println(); // Переход на новую строку для отделения принятых данных
}

Реализация I2C на STM32

Пример кода(С/C++) инициализации интерфейсу I2C частотой 100кГц с использованием микроконтроллера STM32 (CubeMX и HAL библиотеки). Микроконтроллер STM32 будет выступать в роли мастера, а который передает строку «Hello world». Адрес ведомого устройства (в данном случае 0x08) должен быть адаптирован к вашей схеме и адресу ведомого устройства.
...
Копировать
#include "stm32f4xx_hal.h"
#include <stdio.h>
#include <string.h>

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();

  char txBuffer[] = "Hello world";
  HAL_I2C_Master_Transmit(&hi2c1, 0x08 << 1, (uint8_t *)txBuffer, strlen(txBuffer), HAL_MAX_DELAY);

  while (1);
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 16;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_I2C1_Init(void)
{
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
  while (1)
  {
  }
}

Заключение

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

Главная
Курсы
Вебинары
Описание интерфейса I2C: принцип работы, протокол и применение
15 наиболее используемых аппаратных интерфейсов
Интерфейс DMX512: описание и принцип работы
RS485: обзор, примеры на Verilog и С++
UART: обзор, примеры на Verilog и C++
SPI: обзор, примеры на Verilog и C++
Закрыть