From 2f5fcf276cd3dd5b3c49fd756aac82bda5af32a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20de=20Assis=20Madruga=20Prestes?= <104784274+vinicius-de-assis@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:01:53 -0300 Subject: [PATCH] feat(example): Add a I2C Simple example Merges https://github.com/espressif/esp-idf/pull/14315 Closes https://github.com/espressif/esp-idf/issues/14902 --- docs/en/api-reference/peripherals/i2c.rst | 2 + docs/zh_CN/api-reference/peripherals/i2c.rst | 2 + examples/peripherals/.build-test-rules.yml | 6 ++ .../peripherals/i2c/i2c_basic/CMakeLists.txt | 6 ++ examples/peripherals/i2c/i2c_basic/README.md | 51 ++++++++++ .../i2c/i2c_basic/main/CMakeLists.txt | 2 + .../i2c/i2c_basic/main/Kconfig.projbuild | 25 +++++ .../i2c_basic/main/i2c_basic_example_main.c | 93 +++++++++++++++++++ 8 files changed, 187 insertions(+) create mode 100644 examples/peripherals/i2c/i2c_basic/CMakeLists.txt create mode 100644 examples/peripherals/i2c/i2c_basic/README.md create mode 100644 examples/peripherals/i2c/i2c_basic/main/CMakeLists.txt create mode 100644 examples/peripherals/i2c/i2c_basic/main/Kconfig.projbuild create mode 100644 examples/peripherals/i2c/i2c_basic/main/i2c_basic_example_main.c diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index f008024809..f971f4d1a8 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -600,6 +600,8 @@ Kconfig Options Application Examples -------------------- +- :example:`peripherals/i2c/i2c_basic` demonstrates the basic steps to initialize the I2C master driver and read data from a MPU9250 sensor. + - :example:`peripherals/i2c/i2c_eeprom` demonstrates how to use the I2C master mode to read and write data from a connected EEPROM. - :example:`peripherals/i2c/i2c_tools` demonstrates how to use the I2C Tools for developing I2C related applications, providing command-line tools for configuring the I2C bus, scanning for devices, reading and setting registers, and examining registers. diff --git a/docs/zh_CN/api-reference/peripherals/i2c.rst b/docs/zh_CN/api-reference/peripherals/i2c.rst index 845465560a..d2f456837f 100644 --- a/docs/zh_CN/api-reference/peripherals/i2c.rst +++ b/docs/zh_CN/api-reference/peripherals/i2c.rst @@ -600,6 +600,8 @@ Kconfig 选项 应用示例 -------- +- :example:`peripherals/i2c/i2c_basic` 演示了初始化 I2C 主机驱动程序并从 MPU9250 传感器读取数据的基本步骤。 + - :example:`peripherals/i2c/i2c_eeprom` 演示了如何使用 I2C 主机模式从连接的 EEPROM 读取和写入数据。 - :example:`peripherals/i2c/i2c_tools` 演示了如何使用 I2C 工具开发 I2C 相关的应用程序,提供了用于配置 I2C 总线、扫描设备、读取、设置和检查寄存器的命令行工具。 diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index c9d47a4ee7..64b8072ecb 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -67,6 +67,12 @@ examples/peripherals/gpio/matrix_keyboard: enable: - if: IDF_TARGET == "esp32s2" +examples/peripherals/i2c/i2c_basic: + disable: + - if: SOC_I2C_SUPPORTED != 1 + depends_components: + - esp_driver_i2c + examples/peripherals/i2c/i2c_eeprom: disable: - if: SOC_I2C_SUPPORTED != 1 diff --git a/examples/peripherals/i2c/i2c_basic/CMakeLists.txt b/examples/peripherals/i2c/i2c_basic/CMakeLists.txt new file mode 100644 index 0000000000..f49282b1c9 --- /dev/null +++ b/examples/peripherals/i2c/i2c_basic/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(i2c-basic) diff --git a/examples/peripherals/i2c/i2c_basic/README.md b/examples/peripherals/i2c/i2c_basic/README.md new file mode 100644 index 0000000000..ffbc55415e --- /dev/null +++ b/examples/peripherals/i2c/i2c_basic/README.md @@ -0,0 +1,51 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | + +# Basic I2C Master Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## Overview + +This example demonstrates basic usage of I2C driver by reading and writing from a I2C connected sensor: + +If you have a new I2C application to go (for example, read the temperature data from external sensor with I2C interface), try this as a basic template, then add your own code. + +## How to use example + +### Hardware Required + +To run this example, you should have an Espressif development board based on a chip listed in supported targets as well as a MPU9250. MPU9250 is a inertial measurement unit, which contains a accelerometer, gyroscope as well as a magnetometer, for more information about it, you can read the [datasheet of the MPU9250 sensor](https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf). + +#### Pin Assignment + +**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` . + +| | SDA | SCL | +| ---------------- | -------------- | -------------- | +| ESP I2C Master | I2C_MASTER_SDA | I2C_MASTER_SCL | +| MPU9250 Sensor | SDA | SCL | + +For the actual default value of `I2C_MASTER_SDA` and `I2C_MASTER_SCL` see `Example Configuration` in `menuconfig`. + +**Note:** There's no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors. + +### Build and Flash + +Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +```bash +I (328) example: I2C initialized successfully +I (338) example: WHO_AM_I = 71 +I (338) example: I2C de-initialized successfully +``` + +## Troubleshooting + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/peripherals/i2c/i2c_basic/main/CMakeLists.txt b/examples/peripherals/i2c/i2c_basic/main/CMakeLists.txt new file mode 100644 index 0000000000..c34b04c56a --- /dev/null +++ b/examples/peripherals/i2c/i2c_basic/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "i2c_basic_example_main.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/i2c/i2c_basic/main/Kconfig.projbuild b/examples/peripherals/i2c/i2c_basic/main/Kconfig.projbuild new file mode 100644 index 0000000000..79c4a227de --- /dev/null +++ b/examples/peripherals/i2c/i2c_basic/main/Kconfig.projbuild @@ -0,0 +1,25 @@ +menu "Example Configuration" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + + config I2C_MASTER_SCL + int "SCL GPIO Num" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 4 + help + GPIO number for I2C Master clock line. + + config I2C_MASTER_SDA + int "SDA GPIO Num" + range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX + default 5 + help + GPIO number for I2C Master data line. + + config I2C_MASTER_FREQUENCY + int "Master Frequency" + default 400000 + help + I2C Speed of Master device. + +endmenu diff --git a/examples/peripherals/i2c/i2c_basic/main/i2c_basic_example_main.c b/examples/peripherals/i2c/i2c_basic/main/i2c_basic_example_main.c new file mode 100644 index 0000000000..18cade590b --- /dev/null +++ b/examples/peripherals/i2c/i2c_basic/main/i2c_basic_example_main.c @@ -0,0 +1,93 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* i2c - Simple Example + + Simple I2C example that shows how to initialize I2C + as well as reading and writing from and to registers for a sensor connected over I2C. + + The sensor used in this example is a MPU9250 inertial measurement unit. +*/ +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "driver/i2c_master.h" + +static const char *TAG = "example"; + +#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */ +#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */ +#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */ +#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< 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 MPU9250_SENSOR_ADDR 0x68 /*!< Address of the MPU9250 sensor */ +#define MPU9250_WHO_AM_I_REG_ADDR 0x75 /*!< Register addresses of the "who am I" register */ +#define MPU9250_PWR_MGMT_1_REG_ADDR 0x6B /*!< Register addresses of the power management register */ +#define MPU9250_RESET_BIT 7 + +/** + * @brief Read a sequence of bytes from a MPU9250 sensor registers + */ +static esp_err_t mpu9250_register_read(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len) +{ + return i2c_master_transmit_receive(dev_handle, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); +} + +/** + * @brief Write a byte to a MPU9250 sensor register + */ +static esp_err_t mpu9250_register_write_byte(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t data) +{ + uint8_t write_buf[2] = {reg_addr, data}; + return i2c_master_transmit(dev_handle, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); +} + +/** + * @brief i2c master initialization + */ +static void i2c_master_init(i2c_master_bus_handle_t *bus_handle, i2c_master_dev_handle_t *dev_handle) +{ + i2c_master_bus_config_t bus_config = { + .i2c_port = I2C_MASTER_NUM, + .sda_io_num = I2C_MASTER_SDA_IO, + .scl_io_num = I2C_MASTER_SCL_IO, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, bus_handle)); + + i2c_device_config_t dev_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = MPU9250_SENSOR_ADDR, + .scl_speed_hz = I2C_MASTER_FREQ_HZ, + }; + ESP_ERROR_CHECK(i2c_master_bus_add_device(*bus_handle, &dev_config, dev_handle)); +} + +void app_main(void) +{ + uint8_t data[2]; + i2c_master_bus_handle_t bus_handle; + i2c_master_dev_handle_t dev_handle; + i2c_master_init(&bus_handle, &dev_handle); + ESP_LOGI(TAG, "I2C initialized successfully"); + + /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */ + ESP_ERROR_CHECK(mpu9250_register_read(dev_handle, MPU9250_WHO_AM_I_REG_ADDR, data, 1)); + ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]); + + /* Demonstrate writing by resetting the MPU9250 */ + ESP_ERROR_CHECK(mpu9250_register_write_byte(dev_handle, MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT)); + + ESP_ERROR_CHECK(i2c_master_bus_rm_device(dev_handle)); + ESP_ERROR_CHECK(i2c_del_master_bus(bus_handle)); + ESP_LOGI(TAG, "I2C de-initialized successfully"); +}