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.

Comments

  1. vignesh

    3 years ago

    Hi! I am New for esp32. can you brief of how to develop the i2c for reading any sensor data.

    1. Mark

      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.

Comments

Your email address will not be published. Required fields are marked *