【ESP32 IDF】I2C的使用

举报
人才程序员 发表于 2024/03/31 16:51:15 2024/03/31
【摘要】 @TOC 前言ESP32是一款强大的微控制器,广泛应用于物联网(IoT)和嵌入式系统开发。它具备丰富的硬件接口,其中之一是I2C(Inter-Integrated Circuit),这是一种用于短距离通信的串行通信协议。I2C接口常用于连接各种外部传感器、存储器和其他外设,使得ESP32能够轻松实现与外部设备的数据交换。本文将介绍如何在ESP32 IDF中使用I2C接口,提供一个简单而实用的...

@TOC


前言

ESP32是一款强大的微控制器,广泛应用于物联网(IoT)和嵌入式系统开发。它具备丰富的硬件接口,其中之一是I2C(Inter-Integrated Circuit),这是一种用于短距离通信的串行通信协议。I2C接口常用于连接各种外部传感器、存储器和其他外设,使得ESP32能够轻松实现与外部设备的数据交换。

本文将介绍如何在ESP32 IDF中使用I2C接口,提供一个简单而实用的示例代码。通过本文,您将了解如何初始化I2C主机、进行数据写入以及连接和配置I2C从设备的关键步骤。


一、I2C驱动使用的步骤

以下部分将指导您完成 I2C 驱动程序配置和工作的基本步骤:

  • 配置驱动程序 - 设置初始化参数(如主机模式或从机模式,SDA 和 SCL 使用的 GPIO 管脚,时钟速度等)

  • 安装驱动程序- 激活一个 I2C 控制器的驱动,该控制器可为主机也可为从机

  • 根据是为主机还是从机配置驱动程序,选择合适的项目

    • 主机模式下通信 - 发起通信(主机模式)

    • 从机模式下通信 - 响应主机消息(从机模式)

  • 中断处理 - 配置和 I2C 中断服务

  • 用户自定义配置 - 调整默认的 I2C 通信参数(如时序、位序等)

  • 错误处理 - 如何识别和处理驱动程序配置和通信错误

  • 删除驱动程序- 在通信结束时释放 I2C 驱动程序所使用的资源

二、I2C的使用

2.1 配置驱动程序

如果你需要使用I2C,你需要这个结构体:i2c_config_t,他的结构体定义如下:

typedef struct{
    i2c_mode_t mode;     /*!< I2C mode */
    int sda_io_num;      /*!< GPIO number for I2C sda signal */
    int scl_io_num;      /*!< GPIO number for I2C scl signal */
    bool sda_pullup_en;  /*!< Internal GPIO pull mode for I2C sda signal*/
    bool scl_pullup_en;  /*!< Internal GPIO pull mode for I2C scl signal*/

    union {
        struct {
            uint32_t clk_speed;     /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
        } master;                   /*!< I2C master config */
        struct {
            uint8_t addr_10bit_en;  /*!< I2C 10bit address mode enable for slave mode */
            uint16_t slave_addr;    /*!< I2C address for slave mode */
        } slave;                    /*!< I2C slave config */
    };
    uint32_t clk_flags;             /*!< Bitwise of ``I2C_SCLK_SRC_FLAG_**FOR_DFS**`` for clk source choice*/
} i2c_config_t;

mode:
用途:设置I2C接口的工作模式,可以是主机模式(I2C_MODE_MASTER)或从机模式(I2C_MODE_SLAVE)。

主机模式(Master Mode)
在主机模式下,ESP32充当I2C总线的主设备,负责启动和控制通信。主机模式用于与一个或多个I2C从设备进行通信。主机发送起始信号、地址、数据和停止信号,控制整个通信过程。

从机模式(Slave Mode)
在从机模式下,ESP32作为I2C总线上的从设备,等待主机发起通信。ESP32从设备接收来自主机的地址和数据,并根据主机的命令执行相应的操作。从机模式使ESP32能够与其他I2C主机设备通信,实现更复杂的系统互联。

我们使用主机模式即可

sda_io_num:
用途:指定I2C总线的数据线(SDA)连接的GPIO引脚的编号。

scl_io_num:
用途:指定I2C总线的时钟线(SCL)连接的GPIO引脚的编号。

sda_pullup_en:
用途:控制SDA引脚的内部上拉电阻是否启用。

scl_pullup_en:
用途:控制SCL引脚的内部上拉电阻是否启用。

master(union内部的结构体):
用途:当mode为主机模式时,用于配置主机模式下的具体参数。
clk_speed:设置I2C主机模式下的时钟频率,即通信速率。

slave(union内部的结构体):
用途:当mode为从机模式时,用于配置从机模式下的具体参数。
addr_10bit_en:启用或禁用I2C从机模式下的10位地址模式。
slave_addr:设置I2C从机模式下的从机地址。

clk_flags:
用途:通过使用位掩码(bitwise flags)来指定时钟源的选择,具体取值可以是I2C_SCLK_SRC_FLAG_CORE或I2C_SCLK_SRC_FLAG_DFS。

接下来,我们需要为I2C结构体进行初始化,使用这个函数:

esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf)

i2c_num:
意义:指定要配置的I2C总线编号,即I2C控制器的索引。
取值:I2C_NUM_0 或 I2C_NUM_1,表示要配置的是I2C0或I2C1。
在这里插入图片描述
i2c_conf:
意义:指向一个 i2c_config_t 类型的结构体,用于配置I2C总线的参数。
取值:通常情况下,可以通过填充 i2c_config_t 结构体的各个成员来指定具体的配置参数。前面已经介绍过 i2c_config_t 结构体的成员及其作用。

2.2 安装驱动程序

我们可以使用下面这个函数来安装驱动程序:

esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len,
                             int intr_alloc_flags)

i2c_num:
含义:指定要安装和初始化的I2C总线编号,即I2C控制器的索引。
取值:I2C_NUM_0 或 I2C_NUM_1,表示要初始化的是I2C0或I2C1。

mode:
含义:指定I2C总线的工作模式。
取值:可以是 I2C_MODE_MASTER(主机模式)或 I2C_MODE_SLAVE(从机模式)。

slv_rx_buf_len:
含义:指定从机模式下接收缓冲区的大小。
取值:正整数,表示从机模式下接收缓冲区的长度,单位是字节。如果不使用从机模式,则可以将其设置为0。

slv_tx_buf_len:

含义:指定从机模式下发送缓冲区的大小。
取值:正整数,表示从机模式下发送缓冲区的长度,单位是字节。如果不使用从机模式,则可以将其设置为0。

intr_alloc_flags:
含义:指定中断分配的标志位。
取值:可以使用ESP_INTR_FLAG_*系列宏来设置,用于指定中断服务程序的优先级、CPU核心等信息。通常可以选择 ESP_INTR_FLAG_IRAM 或 ESP_INTR_FLAG_SHARED。
如果不使用,写0即可

2.3 主机写入数据

写入数据的过程

主机发送数据有如下的过程:
在这里插入图片描述

  1. 使用 i2c_cmd_link_create() 创建一个命令链接。

    然后,将一系列待发送给从机的数据填充命令链接:

    启动位 - i2c_master_start()

    从机地址 - i2c_master_write_byte()。提供单字节地址作为调用此函数的实参。

    数据 - 一个或多个字节的数据作为 i2c_master_write() 的实参。

    停止位 - i2c_master_stop()

    函数 i2c_master_write_byte()i2c_master_write() 都有额外的实参,规定主机是否应确认其有无接受到 ACK 位。

  2. 通过调用i2c_master_cmd_begin() 来触发 I2C 控制器执行命令链接。一旦开始执行,就不能再修改命令链接。

  3. 命令发送后,通过调用i2c_cmd_link_delete() 释放命令链接使用的资源。

我们就可以写出下面这个函数

// 发送数据到I2C从设备
static esp_err_t i2c_master_send(uint8_t *data, size_t size) {
    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, size, true);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd);
    return ret;
}

接收数据的过程

在这里插入图片描述
在读取数据时,在上图的步骤 4 中,不是用 i2c_master_write…,而是用 i2c_master_read_byte() 和/或 i2c_master_read() 填充命令链接。同样,在步骤 5 中配置最后一次的读取,以便主机不提供 ACK 位。

我们可以写出下面这个代码:

// 从I2C从设备接收数据
static esp_err_t i2c_master_receive(uint8_t *data, size_t size) {
    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);
    if (size > 1) {
        i2c_master_read(cmd, data, size - 1, I2C_MASTER_ACK);
    }
    i2c_master_read_byte(cmd, data + size - 1, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd);
    return ret;
}

我们实现完这几个函数就可以去实现我们的I2C操作了。如果大家需要详细的代码可以进入我的资源找到ESP32-IDF I2C代码


总结

通过本文,我们深入了解了ESP32 IDF中I2C接口的基本使用方法。首先,我们学习了如何初始化I2C主机,包括配置GPIO引脚和设置时钟频率等关键步骤。接着,我们展示了一个简单的示例代码,演示了如何使用ESP32与I2C从设备通信,向其写入数据。

这个示例代码不仅展示了ESP32 IDF中I2C API的基本用法,还为开发者提供了一个起点,可根据实际需求进行定制和扩展。通过理解I2C接口的基本原理和ESP32 IDF中的相关API,开发者可以更轻松地与各种I2C设备进行集成,从而实现更复杂的嵌入式系统和物联网应用。

总体而言,ESP32 IDF为开发者提供了丰富而强大的工具,使得利用ESP32的I2C接口进行通信变得简单而高效。这为物联网和嵌入式系统领域的开发者们带来了更多可能性,同时也推动着这一领域的不断创新和发展。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。