【esp32 idf入门】快速使用i2c发送和接收数据

举报
人才程序员 发表于 2024/07/28 20:28:51 2024/07/28
【摘要】 @TOC 前言ESP32 是一款集成了 Wi-Fi 和 Bluetooth 的高性能低功耗系统级芯片(SoC),广泛应用于物联网 (IoT) 领域。ESP32 支持多种通信协议,其中 I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,用于连接微控制器与外围设备。本文将介绍如何快速在 ESP32 上使用 I2C 协议发送和接收数据,帮助初学者快速上手 ESP-...

@TOC


前言

ESP32 是一款集成了 Wi-Fi 和 Bluetooth 的高性能低功耗系统级芯片(SoC),广泛应用于物联网 (IoT) 领域。ESP32 支持多种通信协议,其中 I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,用于连接微控制器与外围设备。本文将介绍如何快速在 ESP32 上使用 I2C 协议发送和接收数据,帮助初学者快速上手 ESP-IDF(Espressif IoT Development Framework)。


观前须知

上篇I2C文章I2C他的代码也是OK没有问题的,那为什么有这篇文章呢?
原因就是上篇文章的操作方法太过复杂了,还需要什么开始命令这些,非常恶心,idf提供了类似于STM32的Mem模式,使用一个函数即可发送指令读取指定位置的数据

函数介绍

i2c_master_write_read_device

函数原型

esp_err_t i2c_master_write_read_device(
    i2c_port_t i2c_num,
    uint8_t device_address,
    const uint8_t *write_buffer,
    size_t write_size,
    uint8_t *read_buffer,
    size_t read_size,
    TickType_t ticks_to_wait
);

函数作用

该函数用于在 I2C 主设备上执行写操作和读操作,通常用于先发送命令或地址,然后读取从设备的响应数据。它将写入和读取操作结合在一次传输中,减少了通信开销。

参数介绍

  • i2c_port_t i2c_num: I2C 端口号,取值为 I2C_NUM_0I2C_NUM_1,表示使用的 I2C 控制器。
  • uint8_t device_address: I2C 从设备的 7 位地址。
  • const uint8_t *write_buffer: 指向要写入的数据缓冲区的指针。
  • size_t write_size: 要写入的数据字节数。
  • uint8_t *read_buffer: 指向用于存储读取数据的缓冲区的指针。
  • size_t read_size: 要读取的数据字节数。
  • TickType_t ticks_to_wait: 等待完成操作的最大时间,单位是系统时钟节拍数。

返回值

  • ESP_OK: 操作成功。
  • 其他 esp_err_t 错误代码: 操作失败,具体错误码可以帮助诊断问题。

i2c_master_write_to_device

函数原型

esp_err_t i2c_master_write_to_device(
    i2c_port_t i2c_num,
    uint8_t device_address,
    const uint8_t *write_buffer,
    size_t write_size,
    TickType_t ticks_to_wait
);

函数作用

该函数用于在 I2C 主设备上执行写操作,将指定的数据发送到 I2C 从设备。通常用于发送命令、寄存器地址或数据给从设备。

参数介绍

  • i2c_port_t i2c_num: I2C 端口号,取值为 I2C_NUM_0I2C_NUM_1,表示使用的 I2C 控制器。
  • uint8_t device_address: I2C 从设备的 7 位地址。
  • const uint8_t *write_buffer: 指向要写入的数据缓冲区的指针。
  • size_t write_size: 要写入的数据字节数。
  • TickType_t ticks_to_wait: 等待完成操作的最大时间,单位是系统时钟节拍数。

返回值

  • ESP_OK: 操作成功。
  • 其他 esp_err_t 错误代码: 操作失败,具体错误码可以帮助诊断问题。

示例

如果想要更多的示例,请找到你的idf安装目录,找到framework,找到esp-idf-v5.2.2,然后找到examples即可

使用 i2c_master_write_read_device 的示例

假设我们要从 I2C 从设备读取数据前,先发送一个命令:

#include <stdio.h>
#include "driver/i2c.h"

#define I2C_MASTER_SCL_IO 22           // I2C master clock pin
#define I2C_MASTER_SDA_IO 21           // I2C master data pin
#define I2C_MASTER_NUM I2C_NUM_0       // I2C port number
#define I2C_MASTER_FREQ_HZ 100000      // I2C master clock frequency
#define I2C_MASTER_TX_BUF_DISABLE 0    // I2C master doesn't need buffer
#define I2C_MASTER_RX_BUF_DISABLE 0    // I2C master doesn't need buffer
#define I2C_MASTER_TIMEOUT_MS 1000

#define DEVICE_ADDRESS 0x28            // I2C device address
#define WRITE_CMD 0x01                 // Command to be sent to the device

void app_main(void) {
    // Initialize I2C master
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .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);

    uint8_t write_buffer = WRITE_CMD;
    uint8_t read_buffer[10];  // Buffer to store the read data

    esp_err_t ret = i2c_master_write_read_device(
        I2C_MASTER_NUM,
        DEVICE_ADDRESS,
        &write_buffer,
        sizeof(write_buffer),
        read_buffer,
        sizeof(read_buffer),
        pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)
    );

    if (ret == ESP_OK) {
        printf("Data read from device: ");
        for (int i = 0; i < sizeof(read_buffer); i++) {
            printf("%02x ", read_buffer[i]);
        }
        printf("\n");
    } else {
        printf("I2C read failed\n");
    }

    // Clean up
    i2c_driver_delete(I2C_MASTER_NUM);
}

使用 i2c_master_write_to_device 的示例

假设我们要将一些数据发送到 I2C 从设备:

#include <stdio.h>
#include "driver/i2c.h"

#define I2C_MASTER_SCL_IO 22           // I2C master clock pin
#define I2C_MASTER_SDA_IO 21           // I2C master data pin
#define I2C_MASTER_NUM I2C_NUM_0       // I2C port number
#define I2C_MASTER_FREQ_HZ 100000      // I2C master clock frequency
#define I2C_MASTER_TX_BUF_DISABLE 0    // I2C master doesn't need buffer
#define I2C_MASTER_RX_BUF_DISABLE 0    // I2C master doesn't need buffer
#define I2C_MASTER_TIMEOUT_MS 1000

#define DEVICE_ADDRESS 0x28            // I2C device address

void app_main(void) {
    // Initialize I2C master
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .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);

    uint8_t write_buffer[] = {0x01, 0x02, 0x03, 0x04};  // Data to be sent to the device

    esp_err_t ret = i2c_master_write_to_device(
        I2C_MASTER_NUM,
        DEVICE_ADDRESS,
        write_buffer,
        sizeof(write_buffer),
        pdMS_TO_TICKS(I2C_MASTER_TIMEOUT_MS)
    );

    if (ret == ESP_OK) {
        printf("Data written to device successfully\n");
    } else {
        printf("I2C write failed\n");
    }

    // Clean up
    i2c_driver_delete(I2C_MASTER_NUM);
}

总结

通过本文的介绍,我们了解了如何在 ESP32 上使用 ESP-IDF 进行 I2C 通信,包括设置 I2C 配置、初始化 I2C 驱动程序、发送数据和接收数据。I2C 协议的简洁性和高效性,使其成为与传感器、显示屏等外设通信的理想选择。掌握了这些基础操作后,您可以根据实际需求扩展和应用 I2C 通信,为各种 IoT 项目开发奠定坚实的基础。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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