// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include "FreeRTOS.h" #include "esp_err.h" #include "gpio.h" #ifdef __cplusplus extern "C" { #endif typedef enum { I2C_MODE_MASTER, /*!< I2C master mode */ I2C_MODE_MAX, } i2c_mode_t; typedef enum { I2C_MASTER_WRITE = 0, /*!< I2C write data */ I2C_MASTER_READ, /*!< I2C read data */ } i2c_rw_t; typedef enum { I2C_CMD_RESTART = 0, /*!< I2C restart command */ I2C_CMD_WRITE, /*!< I2C write command */ I2C_CMD_READ, /*!< I2C read command */ I2C_CMD_STOP, /*!< I2C stop command */ } i2c_opmode_t; typedef enum { I2C_NUM_0 = 0, /*!< I2C port 0 */ I2C_NUM_MAX } i2c_port_t; typedef enum { I2C_MASTER_ACK = 0x0, /*!< I2C ack for each byte read */ I2C_MASTER_NACK = 0x1, /*!< I2C nack for each byte read */ I2C_MASTER_LAST_NACK = 0x2, /*!< I2C nack for the last byte*/ I2C_MASTER_ACK_MAX, } i2c_ack_type_t; /** * @brief I2C initialization parameters */ typedef struct { i2c_mode_t mode; /*!< I2C mode */ gpio_num_t sda_io_num; /*!< GPIO number for I2C sda signal */ gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/ gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */ gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/ uint32_t clk_stretch_tick; /*!< Clock Stretch time, depending on CPU frequency*/ } i2c_config_t; typedef void *i2c_cmd_handle_t; /*!< I2C command handle */ /** * @brief I2C driver install * * @param i2c_num I2C port number * @param mode I2C mode( master or slave ) * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_FAIL Driver install error */ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode); /** * @brief I2C driver delete * * @param i2c_num I2C port number * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_driver_delete(i2c_port_t i2c_num); /** * @brief I2C parameter initialization * * @note It must be used after calling i2c_driver_install * * @param i2c_num I2C port number * @param i2c_conf pointer to I2C parameter settings * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf); /** * @brief Configure GPIO signal for I2C sck and sda * * @param i2c_num I2C port number * @param sda_io_num GPIO number for I2C sda signal * @param scl_io_num GPIO number for I2C scl signal * @param sda_pullup_en Whether to enable the internal pullup for sda pin * @param scl_pullup_en Whether to enable the internal pullup for scl pin * @param mode I2C mode * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, gpio_pullup_t sda_pullup_en, gpio_pullup_t scl_pullup_en, i2c_mode_t mode); /** * @brief Create and init I2C command link * @note * Before we build I2C command link, we need to call i2c_cmd_link_create() to create * a command link. * After we finish sending the commands, we need to call i2c_cmd_link_delete() to * release and return the resources. * * @return i2c command link handler */ i2c_cmd_handle_t i2c_cmd_link_create(); /** * @brief Free I2C command link * @note * Before we build I2C command link, we need to call i2c_cmd_link_create() to create * a command link. * After we finish sending the commands, we need to call i2c_cmd_link_delete() to * release and return the resources. * * @param cmd_handle I2C command handle */ void i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle); /** * @brief Queue command for I2C master to generate a start signal * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_start(i2c_cmd_handle_t cmd_handle); /** * @brief Queue command for I2C master to write one byte to I2C bus * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * @param data I2C one byte command to write to bus * @param ack_en enable ack check for master * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en); /** * @brief Queue command for I2C master to write buffer to I2C bus * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * @param data data to send * @param data_len data length * @param ack_en enable ack check for master * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t data_len, bool ack_en); /** * @brief Queue command for I2C master to read one byte from I2C bus * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * @param data pointer accept the data byte * @param ack ack value for read command * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t *data, i2c_ack_type_t ack); /** * @brief Queue command for I2C master to read data from I2C bus * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * @param data data buffer to accept the data from bus * @param data_len read data length * @param ack ack value for read command * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_read(i2c_cmd_handle_t cmd_handle, uint8_t *data, size_t data_len, i2c_ack_type_t ack); /** * @brief Queue command for I2C master to generate a stop signal * @note * Only call this function in I2C master mode * Call i2c_master_cmd_begin() to send all queued commands * * @param cmd_handle I2C cmd link * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t i2c_master_stop(i2c_cmd_handle_t cmd_handle); /** * @brief I2C master send queued commands. * This function will trigger sending all queued commands. * The task will be blocked until all the commands have been sent out. * The I2C APIs are not thread-safe, if you want to use one I2C port in different tasks, * you need to take care of the multi-thread issue. * @note * Only call this function in I2C master mode * * @param i2c_num I2C port number * @param cmd_handle I2C command handler * @param ticks_to_wait maximum wait ticks. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error * - ESP_FAIL Sending command error, slave doesn't ACK the transfer. * - ESP_ERR_INVALID_STATE I2C driver not installed or not in master mode. * - ESP_ERR_TIMEOUT Operation timeout because the bus is busy. */ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait); #ifdef __cplusplus } #endif