ESP32 simple i2c communication example

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

ESP32 simple i2c communication example

Postby zazas321 » Wed Oct 06, 2021 9:35 am

Hello. I am now learning about I2C in esp32. I have used i2c multiple times in arduino platform before.

My .c code:

Code: Select all


#include "PCA9539.h"

static const char *TAG = "i2c-simple-example";

#define I2C_MASTER_SCL_IO           22      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           21      /*!< GPIO number used for I2C master data  */
//#define I2C_MASTER_SCL_IO           1      /*!< GPIO number used for I2C master clock */
//#define I2C_MASTER_SDA_IO           2      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          400000                     /*!< 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        /*!< Slave 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 managment register */
//#define MPU9250_RESET_BIT                   7








static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size)
{
    if (size == 0) {
        return ESP_OK;
    }
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | READ_BIT, ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}


 
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}




/**
 * @brief i2c master initialization
 */
esp_err_t i2c_master_init()
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}


void i2c_setup()
{
    uint8_t data[2];
    ESP_ERROR_CHECK(i2c_master_init());
    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(MPU9250_WHO_AM_I_REG_ADDR, data, 1));
    ESP_LOGI(TAG, "WHO_AM_I = %X", data[0]);

    /* Demonstrate writing by reseting the MPU9250 */
    ESP_ERROR_CHECK(mpu9250_register_write_byte(MPU9250_PWR_MGMT_1_REG_ADDR, 1 << MPU9250_RESET_BIT));

    ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
    ESP_LOGI(TAG, "I2C unitialized successfully");
}


and my .h file:

Code: Select all

#ifndef PCA9539_H
#define PCA9539_H
/*
#ifdef __cplusplus
extern "C" {
#endif
*/

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




esp_err_t i2c_master_init();
void i2c_setup();



/*
#ifdef __cplusplus
}
#endif
*/

#endif

This is just an initial setup for my i2c that I have developed my combining some of the example codes I have found on esp-idf example codes.


I would like to clarify 1 thing:
Do I need to implement extra handling for my i2c communications? What I am concerned with is the following situation:

What if I have many FreeRTOS tasks running and one of the task is communicating with my i2c sensor. What if the task that is communicating with the i2c sensor gets stopped due to another higher priority task? I assume the i2c communication will not be sucesfull if the task gets interrupted in the middle of i2c transaction

ESP_Sprite
Posts: 9749
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 simple i2c communication example

Postby ESP_Sprite » Thu Oct 07, 2021 2:50 am

I2C transactions are done in hardware; the I2C communication won't just stop. Even if that were not true, you're being an I2C master here; even if the I2C signal gets delayed because of something else, that is perfectly acceptable as I2C does not have a minimum clock speed.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: ESP32 simple i2c communication example

Postby zazas321 » Thu Oct 07, 2021 11:44 am

I got it. I further inspected the i2c write and i2c read functions that are part of the ESP library. They already have measures such as mutex and semaphore to properly handle the i2c communication

Who is online

Users browsing this forum: kaxx1975 and 147 guests