ESP32 I2C: Настройка кода под master и slave

Содержание

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

Оптимальное использование интерфейса I2C на ESP32

  1. Выбор пинов: При использовании I2C на ESP32 необходимо выбрать соответствующие пины для подключения SDA и SCL. Обычно для этого используются пины GPIO21 (SDA) и GPIO22 (SCL).
  2. Инициализация интерфейса: Для работы с I2C на ESP32 необходимо инициализировать интерфейс. Для этого используется функция i2c_param_config для конфигурации параметров I2C и i2c_driver_install для установки драйвера.
  3. Настройка скорости передачи: ESP32 поддерживает разные скорости передачи данных по интерфейсу I2C. При инициализации интерфейса можно указать нужную скорость с помощью параметра i2c_config_t.
  4. Обработка ошибок: Важно предусмотреть обработку возможных ошибок при работе с интерфейсом I2C, таких как потеря соединения с устройством или неверная конфигурация.

Пример объявления интерфейсов I2C на ESP32

Инициализирует интерфейс I2C, отправляет строку «hello world» и читает ответ от ведомого устройства, затем выводит полученное сообщение на консоль. Пример настройки мастера на C/C++:
#include <stdio.h> #include <string.h> #include "driver/i2c.h" #define I2C_MASTER_SCL_IO 22 /*!< GPIO номер для SCL */ #define I2C_MASTER_SDA_IO 21 /*!< GPIO номер для SDA */ #define I2C_MASTER_NUM I2C_NUM_0 /*!< Номер I2C порта */ #define I2C_MASTER_FREQ_HZ 100000 /*!< Скорость передачи данных I2C */ #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< Отключить буфер передачи */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< Отключить буфер приема */ #define I2C_SLAVE_ADDR 0x28 /*!< Адрес I2C ведомого устройства */ void i2c_master_init() { i2c_config_t conf; conf.mode = I2C_MODE_MASTER; // объявление мастера conf.sda_io_num = I2C_MASTER_SDA_IO; // объявление порты SDA conf.scl_io_num = I2C_MASTER_SCL_IO; // объявление порты SCL conf.sda_pullup_en = GPIO_PULLUP_ENABLE; // вкл подтягивающий резистор к порту SDA conf.scl_pullup_en = GPIO_PULLUP_ENABLE; // вкл подтягивающий резистор к порту SCL conf.master.clk_speed = I2C_MASTER_FREQ_HZ; // частота передачи i2c_param_config(I2C_MASTER_NUM, &conf); i2c_driver_install(I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); } // функция записи void i2c_master_write_slave(uint8_t* data, size_t data_len) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (I2C_SLAVE_ADDR << 1) | I2C_MASTER_WRITE, true); i2c_master_write(cmd, data, data_len, true); i2c_master_stop(cmd); i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); } // функция чтения void i2c_master_read_slave(uint8_t* data, size_t data_len) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (I2C_SLAVE_ADDR << 1) | I2C_MASTER_READ, true); i2c_master_read(cmd, data, data_len, I2C_MASTER_LAST_NACK); i2c_master_stop(cmd); i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); } void app_main() { i2c_master_init(); // Отправка строки "hello world" uint8_t data_to_send[] = "hello world"; i2c_master_write_slave(data_to_send, strlen((char*)data_to_send)); // Задержка для ожидания ответа от ведомого устройства vTaskDelay(1000 / portTICK_PERIOD_MS); // Чтение ответа от ведомого устройства uint8_t data_received[128]; memset(data_received, 0, sizeof(data_received)); i2c_master_read_slave(data_received, sizeof(data_received) - 1); // Печать полученного сообщения printf("Received message: %s\n", data_received); }
Пример настройки устройства под ведомого на C/C++:
#include <stdio.h> #include "driver/i2c.h" #define I2C_SLAVE_SCL_IO 22 /*!< GPIO номер для SCL */ #define I2C_SLAVE_SDA_IO 21 /*!< GPIO номер для SDA */ #define I2C_SLAVE_NUM I2C_NUM_0 /*!< Номер I2C порта */ #define I2C_SLAVE_FREQ_HZ 100000 /*!< Скорость передачи данных I2C */ #define CONFIG_ESP_SLAVE_ADDR 30 /*!< Адрес ведомого устройства */ void i2c_init() { i2c_config_t conf; conf.mode = I2C_MODE_SLAVE; // объявление мастера conf.sda_io_num = I2C_SLAVE_SDA_IO; // объявление линии SDA conf.scl_io_num = I2C_SLAVE_SCL_IO; // объявление линии SCL conf.sda_pullup_en = GPIO_PULLUP_ENABLE; // подтягивание резисторов к линии SDA conf.scl_pullup_en = GPIO_PULLUP_ENABLE; // подтягивание резисторов к линии SCL conf.master.clk_speed = I2C_SLAVE_FREQ_HZ; // скорость передачи conf.clk_flags = 0; conf.slave.slave_addr = CONFIG_ESP_SLAVE_ADDR; conf.slave.addr_10bit_en = 0; i2c_param_config(I2C_SLAVE_NUM, &conf); i2c_driver_install(I2C_SLAVE_NUM, conf.mode, 0, 0, 0); } void app_main() { i2c_init(); // Дальнейший код для работы с устройствами по I2C }

Заключение

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