I2C Pins
Typically you can use any GPIO: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2c.html
To confirm, see the S# series datasheet for the ESP device you are using > Peripheral Pin Configurations
Resources
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/i2c.html
https://github.com/espressif/esp-idf/tree/master/examples/peripherals/i2c
I2C Address
Set as normal byte address including RW at bit 0.
So 0b01101000 is set as 0x68, not (0x68 >> 1)
I2C Master Example
#include "driver/i2c.h"
#include <string.h> //Required for memset()
#define EXAMPLE_I2C_PORT_NUMBER I2C_NUM_1 //I2C port number
#define EXAMPLE_I2C_SCL_GPIO 16 //GPIO pin
#define EXAMPLE_I2C_SDA_GPIO 17 //GPIO pin
#define EXAMPLE_I2C_FREQ_HZ 100000 //!< I2C master clock frequency
#define EXAMPLE_I2C_ADDR 0x98
#define EXAMPLE_I2C_WRITE_BIT I2C_MASTER_WRITE
#define EXAMPLE_I2C_READ_BIT I2C_MASTER_READ
#define EXAMPLE_I2C_ACK_CHECK_EN 0x1
#define EXAMPLE_I2C_ACK_CHECK_DIS 0x0
#define EXAMPLE_I2C_ACK_VAL 0x0
#define EXAMPLE_I2C_NACK_VAL 0x1
//----- CREATE THE I2C PORT -----
int i2c_master_port = EXAMPLE_I2C_PORT_NUMBER;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = EXAMPLE_I2C_SDA_GPIO;
conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
conf.scl_io_num = EXAMPLE_I2C_SCL_GPIO;
conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
conf.master.clk_speed = EXAMPLE_I2C_FREQ_HZ; //I2C frequency is the clock speed for a complete high low clock sequence
i2c_param_config(i2c_master_port, &conf);
i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0); //(i2c_num, mode, slv_rx_buf_len, slv_tx_buf_len, intr_alloc_flags)
//i2c_driver_install(i2c_port, i2c_config.mode, 0, 0, ESP_INTR_FLAG_LOWMED); //<<< Alternative version using non dedicated level 1 interrupt (if you have issues running out of level 1 interrupts)
esp_err_t i2c_ret = ESP_OK;
uint8_t data_h;
uint8_t data_l;
i2c_cmd_handle_t OurI2cCmdHandle = i2c_cmd_link_create();
//----- WRITE BYTES -----
i2c_master_start(OurI2cCmdHandle);
i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_WRITE_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_write_byte(OurI2cCmdHandle, 0x02, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_write_byte(OurI2cCmdHandle, 0x7f, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_stop(OurI2cCmdHandle);
//Send queued commands
i2c_ret = i2c_master_cmd_begin(EXAMPLE_I2C_PORT_NUMBER, OurI2cCmdHandle, (100 / portTICK_PERIOD_MS)); //"(# / portTICK_PERIOD_MS)"=maximum wait time. This task will be blocked until all the commands have been sent (not thread-safe - if you want to use one I2C port in different tasks you need to take care of multi-thread issues)
i2c_cmd_link_delete(OurI2cCmdHandle);
//If you want to know if the device returned NACK:
//if (i2c_ret == ESP_FAIL)
//{
// //NACK returned
//}
if (i2c_ret == ESP_OK)
{
//READ BYTES
printf("I2C Write OK\n");
OurI2cCmdHandle = i2c_cmd_link_create();
i2c_master_start(OurI2cCmdHandle);
i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_READ_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_read_byte(OurI2cCmdHandle, &data_h, EXAMPLE_I2C_ACK_VAL);
i2c_master_read_byte(OurI2cCmdHandle, &data_l, EXAMPLE_I2C_NACK_VAL);
i2c_master_stop(OurI2cCmdHandle);
//Send queued commands
i2c_ret = i2c_master_cmd_begin(EXAMPLE_I2C_PORT_NUMBER, OurI2cCmdHandle, 100 / portTICK_PERIOD_MS); //"(# / portTICK_PERIOD_MS)"=maximum wait time. This task will be blocked until all the commands have been sent (not thread-safe - if you want to use one I2C port in different tasks you need to take care of multi-thread issues)
i2c_cmd_link_delete(OurI2cCmdHandle);
}
else
{
printf("I2C FAILED\n");
}
write, restart, read
i2c_cmd_handle_t OurI2cCmdHandle = i2c_cmd_link_create();
//----- WRITE & READ BYTES -----
i2c_master_start(OurI2cCmdHandle);
i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_WRITE_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_write_byte(OurI2cCmdHandle, 0x02, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_start(OurI2cCmdHandle);
i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_READ_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
i2c_master_read_byte(OurI2cCmdHandle, &data_h, EXAMPLE_I2C_ACK_VAL);
i2c_master_read_byte(OurI2cCmdHandle, &data_l, EXAMPLE_I2C_NACK_VAL);
i2c_master_stop(OurI2cCmdHandle);
//Send queued commands
i2c_ret = i2c_master_cmd_begin(EXAMPLE_I2C_PORT_NUMBER, OurI2cCmdHandle, 100 / portTICK_PERIOD_MS); //"(# / portTICK_PERIOD_MS)"=maximum wait time. This task will be blocked until all the commands have been sent (not thread-safe - if you want to use one I2C port in different tasks you need to take care of multi-thread issues)
i2c_cmd_link_delete(OurI2cCmdHandle);
USEFUL?
We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.
4 years ago
Hi! I am New for esp32. can you brief of how to develop the i2c for reading any sensor data.
3 years ago
Hello vignesh. The example given for the ESP32 reading I2C shows the technique for reading/writing on I2C. Each sensor will have documentation describing its own data details as far as what can or needs to be written or read and when. Once you have a specific sensor in mind, read the documentation and it will give that information.