【ESP32-IDF 笔记】04-I2C配置

简介

I2C是一种串行、同步、多设备、半双工的通信协议,允许多个主机和从机在同一总线上共存。I2C使用两条双向开漏线路:串行数据线(SDA)和串行时钟线(SCL),并通过上拉电阻拉高。

ESP32有2个I2C控制器(也称为端口),负责处理I2C总线上的通信。单个I2C控制器既可以作为主机,也可以作为从机。

通常,I2C从设备具有7位地址或10位地址。ESP32支持I2C标准模式(Sm)和快速模式(Fm),其速率分别可达100KHz和400KHz。

警告:

主模式下 SCL 的时钟频率不应大于 400 KHz

备注:

SCL 的频率受上拉电阻和导线电容的影响。因此,强烈建议用户选择合适的上拉电阻,以使频率准确。上拉电阻器的推荐值通常在 1K 欧姆到 10K 欧姆之间。

请记住,频率越高,上拉电阻应越小(但不小于 1 KOhms)。事实上,大 resistor 会降低电流,这将增加 clock switching time 并降低频率。我们通常推荐 2 KOhms 至 5 KOhms 的范围,但用户可能还需要根据其电流消耗要求进行一些调整。

I2C 时钟配置

  • i2c_clock_source_t::I2C_CLK_SRC_DEFAULT:默认 I2C 源时钟。
  • i2c_clock_source_t::I2C_CLK_SRC_APB:APB 时钟作为 I2C 时钟源。

I2C 文件结构

在这里插入图片描述

需要包含在 I2C 应用程序中的公共标头

  • i2c.h:旧版 I2C API 的头文件(适用于使用旧版驱动程序的应用程序)。
  • i2c_master.h:提供标准通信模式特定 API 的头文件(适用于使用具有主模式的新驱动程序的应用程序)。
  • i2c_slave.h:提供标准通信模式特定 API 的头文件(适用于使用具有从属模式的新驱动程序的应用程序)。

备注:

旧驱动程序不能与新驱动程序共存。Include 以使用旧驱动程序,或其他两个标头以使用新驱动程序。请记住,旧版驱动程序现已弃用,并将在将来删除。i2c.h

已包含在上述标头中的公共标头

  • i2c_types_legacy.h:仅在旧版驱动程序中使用的旧版公共类型。
  • i2c_types.h:提供公共类型的头文件。

功能概述

I2C 驱动程序提供以下服务:

  • 资源分配 - 介绍如何使用适当的配置集分配 I2C 总线。它还介绍了如何在资源完成工作后回收资源。
  • I2C 主控制器 - 涵盖 I2C 主控制器的行为。引入数据传输、数据接收以及数据传输和接收。
  • I2C 从控制器 - 涵盖 I2C 从控制器的行为。涉及数据传输和接收。
  • 电源管理 - 描述不同的源时钟将如何影响功耗。
  • IRAM Safe - 描述有关如何使 I2C 中断在禁用缓存的情况下更好地工作的提示。
  • 线程安全 - 列出驱动程序保证哪些 API 是线程安全的。
  • Kconfig 选项 - 列出支持的 Kconfig 选项,这些选项可以为驱动程序带来不同的效果。

资源配置

I2C 主总线和 I2C 从总线(如果支持)在驱动程序中都由 表示。可用端口在资源池中进行管理,该资源池根据请求分配可用端口。i2c_bus_handle_t

安装 I2C 主总线和设备

I2C 主控器基于总线器件模型设计。因此、需要分别分配 I2C 主总线实例和 I2C 器件实例。
在这里插入图片描述

I2C 主总线需要由以下指定的配置:

  • i2c_master_bus_config_t::i2c_port设置控制器使用的 I2C 端口。
  • i2c_master_bus_config_t::sda_io_num设置串行数据总线 (SDA) 的 GPIO 编号。
  • i2c_master_bus_config_t::scl_io_num设置串行时钟总线 (SCL) 的 GPIO 编号。
  • i2c_master_bus_config_t::clk_source选择 I2C 总线的源时钟。中列出了可用的时钟。有关不同 clock source 对 power consumption 的影响,请参阅 Power Management 部分。
  • i2c_master_bus_config_t::glitch_ignore_cnt设置 Master Bus 的 Glitch Period,如果线路上的 Glitch Period小于此值,可以过滤掉,通常值为 7。
  • i2c_master_bus_config_t::intr_priority设置中断的优先级。如果设置为 ,则驱动程序将使用低优先级或中优先级的中断(优先级可以是 1,2 或 3 之一),否则使用请使用数字形式 (1,2,3) 指示的优先级,而不是位掩码形式 ((1<<1),(1<<2),(1<<3))。0
  • i2c_master_bus_config_t::trans_queue_depth内部传输队列的深度。仅在异步事务中有效。
  • i2c_master_bus_config_t::enable_internal_pullup启用内部 pullups。注意:这不足以在高速频率下拉总线。建议使用合适的外部上拉。

如果指定了 i2c_master_bus_config_t中的配置,用户可以调用 i2c_new_master_bus()来分配并初始化一个 I2C 主机总线。如果此函数正常运行,它将返回 I2C 总线句柄。具体来说,当没有更多的 I2C 端口可用时,此函数将返回ESP_ERR_NOT_FOUND错误。

I2C 主设备需要由以下指定的配置:

  • i2c_device_config_t::dev_addr_length配置从设备的地址位长度。用户可以从枚举器I2C_ADDR_BIT_LEN_7或 I2C_ADDR_BIT_LEN_10(如果支持) 中进行选择。

  • i2c_device_config_t::device_addressI2C 设备原始地址。请直接解析该成员的设备地址。例如,设备地址为 0x28,则解析0x28为 ,

    i2c_device_config_t::device_address,不要携带写/读位。

  • i2c_device_config_t::scl_speed_hz设置此设备的 SCL 线路频率。

  • i2c_device_config_t::scl_wait_us.SCL 等待时间 (在美国)。通常这个值不应该很小,因为 slave stretch 会在很长一段时间内发生。(甚至可以拉伸 12 毫秒)。设置 0 表示使用默认 reg 值。

一旦i2c_device_config_t结构中填充了强制性参数,用户就可以调用i2c_master_bus_add_device()以分配 I2C 设备实例并挂载到主总线。如果 I2C 设备运行正常,此函数将返回 I2C 设备句柄。具体来说,当 I2C 总线没有正确初始化时,调用此函数将返回ESP_ERR_INVALID_ARG错误。

示例

#include "driver/i2c_master.h"

i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
};

i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
通过端口获取 I2C 主手柄

鉴于 i2c 主句柄已经在某个模块(例如音频模块)中初始化,另一个模块(例如视频模块)不方便重用该句柄。我们有一个辅助函数i2c_master_get_bus_handle()用于通过 port 获取初始化的句柄。但是,请确保 handle 已提前初始化。否则将报告错误。

// Source File 1
#include "driver/i2c_master.h"
i2c_master_bus_handle_t bus_handle;
i2c_master_bus_config_t i2c_mst_config = {
    ... // same as others
};
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

// Source File 2
#include "driver/i2c_master.h"
i2c_master_bus_handle_t handle;
ESP_ERROR_CHECK(i2c_master_get_bus_handle(0, &handle));
卸载 I2C 主总线和设备

如果不再需要以前安装的 I2C 总线或设备,建议通过调用i2c_master_bus_rm_device()i2c_del_master_bus()来回收资源,以便释放底层硬件。

安装 I2C 从设备

I2C slave 需要 :

  • i2c_slave_config_t::i2c_port设置控制器使用的 I2C 端口。
  • i2c_slave_config_t::sda_io_num设置串行数据总线 (SDA) 的 GPIO 编号。
  • i2c_slave_config_t::scl_io_num设置串行时钟总线 (SCL) 的 GPIO 编号。
  • i2c_slave_config_t::clk_source选择 I2C 总线的源时钟。i2c_clock_source_t中列出了可用的时钟。有关不同 clock source 对 power consumption 的影响,请参阅 Power Management 部分。
  • i2c_slave_config_t::send_buf_depth设置发送缓冲区长度。
  • i2c_slave_config_t::slave_addr设置从地址
  • i2c_master_bus_config_t::intr_priority设置中断的优先级。如果设置为 ,则驱动程序将使用低优先级或中优先级的中断(优先级可以是 1,2 或 3 之一),否则使用请使用数字形式 (1,2,3) 指示的优先级,而不是位掩码形式 ((1<<1),(1<<2),(1<<3))。请注意,一旦设置了中断优先级,就不能更改,直到i2c_del_master_bus()被调用。0
  • i2c_slave_config_t::addr_bit_len如果需要从站具有 10 位地址,则设置为 true。

一旦i2c_slave_config_t结构填充了强制性参数,用户就可以调用i2c_new_slave_device()以分配和初始化 I2C 主总线。如果此函数正常运行,它将返回 I2C 总线句柄。具体来说,当没有更多的 I2C 端口可用时,此函数将返回ESP_ERR_NOT_FOUND错误。

i2c_slave_config_t i2c_slv_config = {
    .addr_bit_len = I2C_ADDR_BIT_LEN_7,
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .send_buf_depth = 256,
    .scl_io_num = I2C_SLAVE_SCL_IO,
    .sda_io_num = I2C_SLAVE_SDA_IO,
    .slave_addr = 0x58,
};

i2c_slave_dev_handle_t slave_handle;
ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &slave_handle));
卸载 I2C 从设备

如果不再需要以前安装的 I2C 总线,建议通过调用 i2c_del_slave_device()来回收资源,以便释放底层硬件。

I2C 主控制器

通过 i2c_new_master_bus()安装 i2c 主驱动后,ESP32 就可以与其他 I2C 设备通信了。I2C API 允许标准事务。像这样挥手:

在这里插入图片描述

I2C 主机写入数据

成功安装 I2C 主总线后,您只需调用i2c_master_transmit()即可将数据写入从设备。这个函数的原理可以用下图来解释。

为了组织该过程,驱动程序使用命令链接,该链接应填充一系列命令,然后传递给 I2C 控制器执行。

在这里插入图片描述
将数据写入 从机 的简单示例:

#define DATA_LENGTH 100
i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = I2C_PORT_NUM_0,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
};
i2c_master_bus_handle_t bus_handle;

ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));

ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1));
I2C 主机读取数据

成功安装 I2C 主总线后,您只需调用i2c_master_receive()即可从从设备读取数据。这个函数的原理可以用下图来解释。
在这里插入图片描述
从 从机 读取数据的简单示例:

#define DATA_LENGTH 100
i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = I2C_PORT_NUM_0,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
};
i2c_master_bus_handle_t bus_handle;

ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));

i2c_master_receive(dev_handle, data_rd, DATA_LENGTH, -1);
I2C 主机写/读数据

一些 I2C 设备在从中读取数据之前需要写入配置,因此,一个名为i2c_master_transmit_receive()函数 可以提供帮助。这个函数的原理可以用下图来解释。
在这里插入图片描述

从 slave 写入和读取的简单示例:

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2C_PORT_NUM_0, &dev_cfg, &dev_handle));
uint8_t buf[20] = {0x20};
uint8_t buffer[2];
ESP_ERROR_CHECK(i2c_master_transmit_receive(i2c_bus_handle, buf, sizeof(buf), buffer, 2, -1));
I2C 主机探针

I2C 驱动程序可使用i2c_master_probe()检测特定设备是否已连接到 I2C 总线上。如果此函数返回 ,则表示已检测到该设备。ESP_OK

注意:

调用此函数时,上拉电阻必须连接到 SCL 和 SDA 引脚。如果在正确解析 xfer_timeout_ms 时得到 ESP_ERR_TIMEOUT,则应检查 pull-up resistors。如果附近没有合适的 resistor,将 flags.enable_internal_pullup 设置为 true 也是可以接受的。

探测 I2C 器件的简单示例

i2c_master_bus_config_t i2c_mst_config_1 = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;

ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config_1, &bus_handle));
ESP_ERROR_CHECK(i2c_master_probe(bus_handle, 0x22, -1));
ESP_ERROR_CHECK(i2c_del_master_bus(bus_handle));

I2C 从机控制器

通过i2c_new_slave_device() 安装 i2c slave 驱动程序后,ESP32 就可以作为 slave 与其他 I2C Master 通信了。

I2C 从机写入数据

I2C slave 的 send buffer 用作 FIFO 来存储要发送的数据。数据将排队,直到 主机 请求它们。您可以调用 i2c_slave_transmit()发送数据。

将数据写入 FIFO 的简单示例:

uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);

i2c_slave_config_t i2c_slv_config = {
    .addr_bit_len = I2C_ADDR_BIT_LEN_7,   // 7-bit address
    .clk_source = I2C_CLK_SRC_DEFAULT,    // set the clock source
    .i2c_port = 0,                        // set I2C port number
    .send_buf_depth = 256,                // set tx buffer length
    .scl_io_num = 2,                      // SCL gpio number
    .sda_io_num = 1,                      // SDA gpio number
    .slave_addr = 0x58,                   // slave address
};

i2c_bus_handle_t i2c_bus_handle;
ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &i2c_bus_handle));
for (int i = 0; i < DATA_LENGTH; i++) {
    data_wr[i] = i;
}

ESP_ERROR_CHECK(i2c_slave_transmit(i2c_bus_handle, data_wr, DATA_LENGTH, 10000));
I2C 从机读取数据

每当 主机 向 从机 写入数据时,从机 会自动将数据存储在接收缓冲区中。这允许从属应用程序自行决定调用函数i2c_slave_receive()。Asi2c_slave_receive() 设计为非阻塞接口。因此,用户需要通过i2c_slave_register_event_callbacks()注册回调函数 才能知道接收何时完成。

static IRAM_ATTR bool i2c_slave_rx_done_callback(i2c_slave_dev_handle_t channel, const i2c_slave_rx_done_event_data_t *edata, void *user_data)
{
    BaseType_t high_task_wakeup = pdFALSE;
    QueueHandle_t receive_queue = (QueueHandle_t)user_data;
    xQueueSendFromISR(receive_queue, edata, &high_task_wakeup);
    return high_task_wakeup == pdTRUE;
}

uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
uint32_t size_rd = 0;

i2c_slave_config_t i2c_slv_config = {
    .addr_bit_len = I2C_ADDR_BIT_LEN_7,
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .send_buf_depth = 256,
    .scl_io_num = I2C_SLAVE_SCL_IO,
    .sda_io_num = I2C_SLAVE_SDA_IO,
    .slave_addr = 0x58,
};

i2c_slave_dev_handle_t slave_handle;
ESP_ERROR_CHECK(i2c_new_slave_device(&i2c_slv_config, &slave_handle));

s_receive_queue = xQueueCreate(1, sizeof(i2c_slave_rx_done_event_data_t));
i2c_slave_event_callbacks_t cbs = {
    .on_recv_done = i2c_slave_rx_done_callback,
};
ESP_ERROR_CHECK(i2c_slave_register_event_callbacks(slave_handle, &cbs, s_receive_queue));

i2c_slave_rx_done_event_data_t rx_data;
ESP_ERROR_CHECK(i2c_slave_receive(slave_handle, data_rd, DATA_LENGTH));
xQueueReceive(s_receive_queue, &rx_data, pdMS_TO_TICKS(10000));
// Receive done.

注册事件回调

I2C 主机回调

当 I2C 主总线触发中断时,将生成特定事件并通知 CPU。如果有一些函数需要在这些事件发生时调用,则可以通过调用 i2c_master_register_event_callbacks()将函数挂接到 ISR(中断服务例程)。由于注册的回调函数是在中断上下文中调用的,因此用户应确保回调函数不会尝试阻塞(例如,确保仅从函数内部调用带有后缀的 FreeRTOS API)。回调函数需要返回一个布尔值,以告诉 ISR 是否唤醒了高优先级任务。ISR

I2C 主事件回调在i2c_master_event_callbacks_t.

虽然 I2C 是一种同步通信协议,但我们也通过注册上述回调来支持异步行为。这样,I2C API 将成为非阻塞接口。但需要注意的是,在同一条总线上,只有一个设备可以采用异步作。

注意:

I2C 主机异步事务仍然是一个实验性功能。(问题是当异步事务非常大时,会导致内存问题。)

I2C 从机回调

当 I2C 从总线触发中断时,将生成特定事件并通知 CPU。如果有一些函数需要在这些事件发生时调用,则可以通过调用 i2c_slave_register_event_callbacks()将函数挂接到 ISR(中断服务例程)。由于注册的回调函数是在中断上下文中调用的,因此用户应确保回调函数不会尝试阻塞(例如,确保仅从函数内部调用带有后缀的 FreeRTOS API)。回调函数有一个布尔返回值,用于告诉调用者是否唤醒了高优先级任务。ISR

I2C 从事件回调在 i2c_slave_event_callbacks_t.中列出。

  • i2c_slave_event_callbacks_t::on_recv_done为 “receive-done” 事件设置回调函数。函数原型在i2c_slave_received_callback_t. 中声明。

主机 API 参考

头文件

#include "driver/i2c_master.h"

需要再CMakeLists.txt添加

REQUIRES driver

PRIV_REQUIRES driver

功能函数

分配 I2C 主总线
esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_master_bus_handle_t *ret_bus_handle)

参数

  • bus_config[in] I2C 主总线配置。

  • ret_bus_handle[out] I2C 总线手柄

返回

  • ESP_OK:I2C 主总线初始化成功。

  • ESP_ERR_INVALID_ARG:由于参数无效,I2C 总线初始化失败。

  • ESP_ERR_NO_MEM:由于 内存不足,创建 I2C 总线失败。

  • ESP_ERR_NOT_FOUND:不再有免费巴士。

添加 I2C 主 BUS 设备
esp_err_t i2c_master_bus_add_device(i2c_master_bus_handle_t bus_handle、const i2c_device_config_t *dev_config、i2c_master_dev_handle_t *ret_handle)

参数

  • bus_handle[in] I2C 总线手柄。

  • dev_config[in] 设备配置。

  • ret_handle[out] 设备句柄。

返回

  • ESP_OK:成功创建 I2C 主设备。

  • ESP_ERR_INVALID_ARG:由于参数无效,I2C 总线初始化失败。

  • ESP_ERR_NO_MEM:由于 内存不足,创建 I2C 总线失败。

取消初始化 I2C 主总线并删除句柄
esp_err_t i2c_del_master_bus(i2c_master_bus_handle_t bus_handle)

参数

  • bus_handle[in] I2C 总线手柄。

返回

  • ESP_OK:删除 I2C 总线成功,否则失败。

  • 其他:某些模块删除失败。

I2C 主总线删除设备
esp_err_t i2c_master_bus_rm_device(i2c_master_dev_handle_t handle)

参数

  • handle – I2C 设备句柄

返回

  • ESP_OK:如果设备删除成功。
I2C 主机发送数据
esp_err_t i2c_master_transmit(i2c_master_dev_handle_t i2c_dev、const uint8_t *write_buffer、size_t write_size、int xfer_timeout_ms)

参数

  • i2c_dev – 由 创建的 I2C 主器件句柄。i2c_master_bus_add_device

  • write_buffer[in] 在 I2C 总线上发送的数据字节。

  • write_size[in] 写缓冲区的大小 (以字节为单位)。

  • xfer_timeout_ms[in] 等待超时,以毫秒为单位。注意:-1 表示永远等待。

返回

  • ESP_OK:I2C 主站发送成功

  • ESP_ERR_INVALID_ARG:I2C 主控发送参数无效。

  • ESP_ERR_TIMEOUT:由于总线繁忙或硬件崩溃,作超时(大于 xfer_timeout_ms)。

注意:

  1. 如果 回调已注册 ,则事务将是异步的,因此,此函数将直接返回,而不会阻塞。您将从 callback 获得完成信息。此外,注册 callback 时,数据缓冲区应始终准备好,否则会导致数据损坏。i2c_master_register_event_callbacks
  2. 在 I2C 总线上执行写入事务。事务将一直进行,直到完成或达到提供的超时。
I2C 主机发送 /接收 数据
esp_err_t i2c_master_transmit_receive(i2c_master_dev_handle_t i2c_dev, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer、size_t read_size、int xfer_timeout_ms)

参数

  • i2c_dev – 由 创建的 I2C 主器件句柄。i2c_master_bus_add_device

  • write_buffer[in] 在 I2C 总线上发送的数据字节。

  • write_size[in] 写缓冲区的大小 (以字节为单位)。

  • read_buffer[out] 从 i2c 总线接收到的数据字节。

  • read_size[in] 读取缓冲区的大小 (以字节为单位)。

  • xfer_timeout_ms[in] 等待超时,以毫秒为单位。注意:-1 表示永远等待。

返回

  • ESP_OK:I2C 主站发送-接收成功

  • ESP_ERR_INVALID_ARG:I2C 主控发送参数无效。

  • ESP_ERR_TIMEOUT:由于总线繁忙或硬件崩溃,作超时(大于 xfer_timeout_ms)。

注意:

  1. 如果 回调已注册 ,则事务将是异步的,因此,此函数将直接返回,而不会阻塞。您将从 callback 获得完成信息。此外,注册 callback 时,数据缓冲区应始终准备好,否则会导致数据损坏。i2c_master_register_event_callbacks
  2. 在 I2C 总线上执行 write-read transaction 。事务将一直进行,直到完成或达到提供的超时。
I2C 主机接收数据
esp_err_t i2c_master_receive(i2c_master_dev_handle_t i2c_dev、uint8_t *read_buffer、size_t read_size、int xfer_timeout_ms)

参数

  • i2c_dev – 由 创建的 I2C 主器件句柄。i2c_master_bus_add_device

  • read_buffer[out] 从 i2c 总线接收到的数据字节。

  • read_size[in] 读取缓冲区的大小 (以字节为单位)。

  • xfer_timeout_ms[in] 等待超时,以毫秒为单位。注意:-1 表示永远等待。

返回* ESP_OK:I2C 主站接收成功

  • ESP_ERR_INVALID_ARG:I2C 主接收参数无效。
  • ESP_ERR_TIMEOUT:由于总线繁忙或硬件崩溃,作超时(大于

注意:

  1. 如果 回调已注册 ,则事务将是异步的,因此,此函数将直接返回,而不会阻塞。您将从 callback 获得完成信息。此外,注册 callback 时,数据缓冲区应始终准备好,否则会导致数据损坏。i2c_master_register_event_callbacks
  2. 在 I2C 总线上执行读取事务。事务将一直进行,直到完成或达到提供的超时。
探测 I2C 地址
esp_err_t i2c_master_probe(i2c_master_bus_handle_t bus_handle、uint16_t address、int xfer_timeout_ms)

参数

  • bus_handle – 由 创建的 I2C 主器件句柄。i2c_master_bus_add_device

  • address – 要探测的 I2C 设备地址。

  • xfer_timeout_ms[in] 等待超时,以毫秒为单位。注意:-1 表示永远等待(此功能不推荐)。

返回* ESP_OK:I2C 器件探测成功

  • ESP_ERR_NOT_FOUND: I2C 探测失败,找不到您提供的特定地址的设备。
  • ESP_ERR_TIMEOUT:由于总线繁忙或硬件崩溃,作超时(大于 xfer_timeout_ms)。

注意:

  1. 探测 I2C 地址,如果地址正确且收到 ACK,则此函数将返回 ESP_OK。
  2. 调用此函数时,上拉电阻必须连接到 SCL 和 SDA 引脚。
  3. 此功能的原理是通过 write 命令发送设备地址。如果器件位于 I2C 总线上,则会出现 ACK 信号,并且函数返回。如果器件不在您的 I2C 总线上,则会有 NACK 信号并且函数返回。 不是预期的故障,这表明 I2C 探针工作不正常,通常是上拉电阻没有正确连接造成的。建议检查 SDA/SCL 线路上的数据,当 i2c 探测功能失败时,查看是否有 ACK/NACK 信号在线。
  4. 世界上有很多 I2C 设备,我们假设并非所有 I2C 设备都支持这样的行为。因此,如果在线数据很奇怪并且没有 ack/nack 得到响应。请查看器件数据表。device_address+nack/ack
为主设备注册 I2C 事务回调
esp_err_t i2c_master_register_event_callbacks(i2c_master_dev_handle_t i2c_dev, const i2c_master_event_callbacks_t *cbs, void *user_data)

参数

  • i2c_dev – 由 创建的 I2C 主器件句柄。i2c_master_bus_add_device

  • cbs[in] 回调函数组

  • user_data[in] 用户数据,将直接传递给回调函数

返回* ESP_OK:成功设置 I2C 事务回调

  • ESP_ERR_INVALID_ARG:设置 I2C 事务回调因参数无效而失败
  • ESP_FAIL:设置I2C事务回调因其他错误而失败

注意:

  1. 用户可以通过调用此函数并将结构中的回调成员设置为 NULL 来取消注册以前注册的回调。
  2. 启用 CONFIG_I2C_ISR_IRAM_SAFE 后,回调本身及其调用的函数应放置在 IRAM 中。函数中使用的变量也应该在 SRAM 中。也应驻留在 SRAM 中。
  3. 如果该回调用于帮助异步事务。在同一总线上,只有一个设备可用于执行异步作。
重置 I2C 主总线
esp_err_t i2c_master_bus_reset(i2c_master_bus_handle_t bus_handle)

参数

  • bus_handle – I2C 总线手柄。

返回* ESP_OK:重置成功。

  • ESP_ERR_INVALID_ARG:I2C 主总线手柄未初始化。
  • 否则:重置失败。
等待所有待处理的 I2C 事务完成
esp_err_t i2c_master_bus_wait_all_done(i2c_master_bus_handle_t bus_handle, int timeout_ms)

参数* bus_handle[in] I2C 总线手柄

  • timeout_ms[in] 等待超时,以毫秒为单位。特别是,-1 表示永远等待。

返回* ESP_OK:刷新交易成功

  • ESP_ERR_INVALID_ARG:由于参数无效,刷新事务失败
  • ESP_ERR_TIMEOUT:由于超时,刷新事务失败
  • ESP_FAIL:由于其他错误,刷新事务失败
检索指定 I2C 端口号的 I2C 主总线句柄
esp_err_t i2c_master_get_bus_handle(i2c_port_num_t port_num, i2c_master_bus_handle_t *ret_handle)

参数

  • port_num – 要检索其句柄的 I2C 端口号。

  • ret_handle – 指向将存储检索到的句柄的变量的指针。

返回* ESP_OK:成功。已成功检索 handle。

  • ESP_ERR_INVALID_ARG:参数无效,例如端口号无效
  • ESP_ERR_INVALID_STATE:无效状态,例如 I2C 端口未初始化。

注意:

此函数检索给定 I2C 端口号的 I2C 主总线句柄。请确保 handle 已初始化,此函数将仅返回现有 handle。请注意,返回的 handle 仍然不能并发使用

从机 API参考

头文件

#include "driver/i2c_slave.h"

功能函数

I2C 从设备初始化
esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave_dev_handle_t *ret_handle)

初始化 I2C 从设备。

参数

  • slave_config[in] I2C 从器件配置

  • ret_handle[out] 返回通用 I2C 器件句柄

返回* ESP_OK:I2C 从设备初始化成功

  • ESP_ERR_INVALID_ARG:由于参数无效,I2C 设备初始化失败。
  • ESP_ERR_NO_MEM:由于内存不足,创建 I2C 设备失败。
I2C 从设备 取消初始化
esp_err_t i2c_del_slave_device(i2c_slave_dev_handle_t i2c_slave)

参数

  • i2c_slave – 由 创建的 I2C 从器件句柄。i2c_new_slave_device

返回* ESP_OK:成功删除 I2C 设备。

  • ESP_ERR_INVALID_ARG:由于参数无效,I2C 设备初始化失败。
I2C 从机 从内部缓冲区读取字节。

启动作业以接收 I2C 数据。

esp_err_t i2c_slave_receive(i2c_slave_dev_handle_t i2c_slave、uint8_t *data、size_t buffer_size)

参数

  • i2c_slave – 由 创建的 I2C 从器件句柄。i2c_new_slave_device

  • data – [out] 用于存储来自 I2C fifo 的数据的缓冲区。在 触发 之前 应有效。on_recv_done

  • buffer_size[in] 用户提供的数据的缓冲区大小。

返回* ESP_OK: I2C slave 接收成功。

  • ESP_ERR_INVALID_ARG:I2C slave 接收参数无效。
  • ESP_ERR_NOT_SUPPORTED:此功能应在 fifo 模式下工作,但配置了 I2C_SLAVE_NONFIFO 模式

注意:

此函数是非阻塞的,它启动新的接收作业,然后返回。用户应检查从 注册的回调中接收到的数据。on_recv_donei2c_slave_register_event_callbacks()

I2C 从机发送数据
esp_err_t i2c_slave_transmit(i2c_slave_dev_handle_t i2c_slave, const uint8_t *data, int size, int xfer_timeout_ms)

参数

  • i2c_slave – 由 创建的 I2C 从器件句柄。i2c_new_slave_device

  • data – [in] 写入 slave fifo 的缓冲区,可以由 master 拾取。可以在此函数返回后释放。等于或大于 。size

  • size – [in] 缓冲区的字节数。data

  • xfer_timeout_ms[in] 等待超时,以毫秒为单位。注意:-1 表示永远等待。

返回* ESP_OK:I2C slave 发送成功。

  • ESP_ERR_INVALID_ARG:I2C slave 发送参数无效。
  • ESP_ERR_TIMEOUT:设备繁忙或硬件崩溃导致作超时(大于 xfer_timeout_ms)。
  • ESP_ERR_NOT_SUPPORTED:此功能应在 fifo 模式下工作,但配置了 I2C_SLAVE_NONFIFO 模式

注意:

  1. 将字节写入 I2C slave 数据的内部 ringbuffer。当 TX fifo 为空时, ISR 将用内部 ringbuffer 的数据填充硬件 FIFO。
  2. 如果将此 Slave 设备连接到某个 Master 设备,则数据事务方向是从 Slave 设备到 Master 设备。
为 I2C slave 通道设置 I2C slave 事件回调
esp_err_t i2c_slave_register_event_callbacks(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_event_callbacks_t *cbs, void *user_data)

参数

  • i2c_slave – 由 创建的 I2C 从器件句柄。i2c_new_slave_device

  • cbs[in] 回调函数组

  • user_data[in] 用户数据,将直接传递给回调函数

返回* ESP_OK:成功设置 I2C 事务回调

  • ESP_ERR_INVALID_ARG:设置 I2C 事务回调因参数无效而失败
  • ESP_FAIL:设置I2C事务回调因其他错误而失败

注意

  1. 用户可以通过调用此函数并将结构中的回调成员设置为 NULL 来取消注册以前注册的回调。cbs
  2. 启用 CONFIG_I2C_ISR_IRAM_SAFE 后,回调本身及其调用的函数应放置在 IRAM 中。函数中使用的变量也应该在 SRAM 中。也应驻留在 SRAM 中。user_data
<think>好的,我需要回答用户关于ESP32-S3-Touch-LCD-2.8C的显示芯片和触摸芯片的具体型号及详细信息的问题。首先,根据用户提供的引用内容,显示驱动是ST7701S,触摸控制器是GT911。我需要详细说明这两个芯片的相关信息。 首先,确认引用[1]提到ESP32-S3配置了ST7701S屏幕驱动和GT911触摸驱动,并关联到LVGL 8.3.0。引用[2]则补充了应用场景,比如智能屏控开关和手势识别。用户需要的是这两个芯片的详细资料,所以需要分别整理ST7701S和GT911的技术规格、功能特点、应用场景等。 对于ST7701S,我需要查找它的数据手册或官方资料,了解其支持的接口类型(如RGB、SPI)、分辨率支持、颜色深度、电源要求、刷新率等。同时,结合引用中提到的ESP32-S3的配置,说明如何集成该驱动,可能涉及到的配置参数或代码结构。 关于GT911,同样需要技术参数,比如支持的触摸点数、通信接口(I2C)、分辨率、多点触控能力、校准方式等。还要提到在ESP32-S3上的配置,比如中断处理、数据读取方式,以及如何与LVGL结合实现触摸输入。 此外,用户可能还想知道如何获取这些芯片的数据手册,或者相关的开发资源,比如示例代码、配置指南。需要确保回答中提到的信息准确,并正确引用提供的资料,比如在适当的位置添加[^1]和[^2]。 可能还需要考虑用户的实际应用场景,如智能家居控制面板,因此可以结合引用[2]提到的双指叩击和接近感应功能,说明GT911如何支持这些手势识别,以及ST7701S在显示效果上的优势,比如高刷新率或低功耗特性。 最后,生成的相关问题需要围绕这两个芯片的配置、常见问题、优化方法等,帮助用户进一步探索。例如,如何配置ST7701S的显示参数,或者如何处理GT911的触摸中断信号。 总结步骤: 1. 确认显示驱动和触摸控制器的型号。 2. 分别介绍两者的技术规格和功能。 3. 结合ESP32-S3的配置示例,说明集成方法。 4. 引用提供的资料,确保信息准确。 5. 生成相关问题,引导用户深入学习。</think>### ESP32-S3-Touch-LCD-2.8C 显示与触摸芯片信息 #### 1. **显示驱动芯片 ST7701S** ST7701S 是专为中小尺寸 RGB 接口 LCD 设计的显示驱动芯片,常用于嵌入式设备的屏幕控制。以下是其核心特性: - **接口类型**:支持 RGB 接口(如 16/18/24 位并行 RGB),兼容 SPI 配置模式。 - **分辨率支持**:最高支持 480×480 像素,适合 2.8 英寸屏幕。 - **颜色深度**:支持 16.7M 色(RGB 8:8:8 模式)。 - **电源管理**:内置 DC-DC 转换器,支持宽电压输入(2.5V–3.3V)。 - **功能特性**:支持 Gamma 校正、图像增强、低功耗模式等。 **集成示例** 在 ESP32-S3 中,需通过 IDF 框架配置 RGB 面板参数(如时序、时钟频率),并编写初始化命令序列。例如: ```c // ST7701S 初始化命令示例 static const st7701s_cmd_t init_cmds[] = { {0xFF, {0x77,0x01,0x00,0x00,0x10}, 5}, {0x11, {0x00}, 0}, // 退出睡眠模式 // 更多配置命令... }; ``` #### 2. **触摸控制器 GT911** GT911 是电容式触摸屏控制器,支持多点触控和手势识别: - **触摸点数**:最多 5 点触控。 - **通信接口**:I2C 或 SPI,默认地址为 0x14/0x5D[^1]。 - **分辨率**:可配置,最高支持 4096×4096。 - **功能特性**:自动校准、抗干扰算法、低功耗模式。 - **手势支持**:支持双指叩击、滑动等(如引用[2]中的智能开关应用)。 **配置要点** - **中断处理**:需配置 ESP32-S3 的 GPIO 中断引脚,响应触摸事件。 - **数据读取**:通过 I2C 读取坐标和触摸状态,并映射到 LVGL 输入接口。 ```c // GT911 数据读取示例 void gt911_read_data() { i2c_read(TOUCH_ADDR, DATA_REG, buffer, 8); // 解析坐标并传递给 LVGL } ``` #### 3. **开发资源** - **ST7701S 数据手册**:需联系厂商或通过[立创商城](https://www.szlcsc.com/)获取。 - **GT911 开发指南**:参考[汇顶科技官网](https://www.goodix.com/)的应用笔记- **ESP32-S3 配置示例**:引用[1]中的 IDF 5.23 `rgb_panel` 驱动框架。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Hwang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值