i2c: update api reference and example pin defination

This commit is contained in:
Cao Sen Miao 2021-02-18 17:45:14 +08:00
parent 1d5828b433
commit 372584d1de
4 changed files with 77 additions and 17 deletions

View File

@ -10,8 +10,13 @@ I2C is a serial, synchronous, half-duplex communication protocol that allows co-
With such advantages as simplicity and low manufacturing cost, I2C is mostly used for communication of low-speed peripheral devices over short distances (within one foot). With such advantages as simplicity and low manufacturing cost, I2C is mostly used for communication of low-speed peripheral devices over short distances (within one foot).
{IDF_TARGET_NAME} has two I2C controllers (also referred to as ports) which are responsible for handling communications on two I2C buses. Each I2C controller can operate as master or slave. As an example, one controller can act as a master and the other as a slave at the same time. .. only:: esp32c3
{IDF_TARGET_NAME} has only one I2C controller (also referred to as port) which is responsible for handling communications on I2C bus. The I2C controller can operate as master or slave.
.. only:: not esp32c3
{IDF_TARGET_NAME} has two I2C controllers (also referred to as ports) which are responsible for handling communications on the I2C bus. Each I2C controller can operate as master or slave. As an example, one controller can act as a master and the other as a slave at the same time.
Driver Features Driver Features
--------------- ---------------
@ -140,10 +145,34 @@ When :cpp:member:`i2c_config_t::clk_flags` is 0, the clock allocator will select
- :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`, :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP` - :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`, :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`
Explanations for :cpp:member:`i2c_config_t::clk_flags` are as follows: Explanations for :cpp:member:`i2c_config_t::clk_flags` are as follows:
1. :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`: Clock's baud rate will not change while APB clock is changing. 1. :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`: Clock's baud rate will not change while APB clock is changing.
2. :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`: It supports Light-sleep mode, which APB clock cannot do. 2. :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`: It supports Light-sleep mode, which APB clock cannot do.
.. only:: esp32c3
.. list-table:: Characteristics of {IDF_TARGET_NAME} clock sources
:widths: 5 5 50 100
:header-rows: 1
* - Clock name
- Clock frequency
- MAX freq for SCL
- Clock capabilities
* - XTAL clock
- 40 MHz
- 2 MHz
- /
* - RTC clock
- 20 MHz
- 1 MHz
- :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`, :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`
Explanations for :cpp:member:`i2c_config_t::clk_flags` are as follows:
1. :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`: Clock's baud rate will not change while APB clock is changing.
2. :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`: It supports Light-sleep mode, which APB clock cannot do.
3. Some flags may not be supported on {IDF_TARGET_NAME}, reading technical reference manual before using it.
.. note:: .. note::
The clock frequency of SCL in master mode should not be lager than max frequency for SCL mentioned in the table above. The clock frequency of SCL in master mode should not be lager than max frequency for SCL mentioned in the table above.

View File

@ -7,7 +7,7 @@
This example demonstrates basic usage of I2C driver by running two tasks on I2C bus: This example demonstrates basic usage of I2C driver by running two tasks on I2C bus:
1. Read external I2C sensor, here we take the BH1750 ambient light sensor (GY-30 module) for an example. 1. Read external I2C sensor, here we take the BH1750 ambient light sensor (GY-30 module) for an example.
2. Use one of ESP32s I2C port (master mode) to read and write another I2C port (slave mode) in ESP32. 2. Use one of the ESP device's I2C port (master mode) to read and write another I2C port (slave mode) in ESP device.
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. 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.
@ -15,17 +15,17 @@ If you have a new I2C application to go (for example, read the temperature data
### Hardware Required ### Hardware Required
To run this example, you should have one ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC). Optionally, you can also connect an external sensor, here we choose the BH1750 just for an example. BH1750 is a digital ambient light sensor, for more information about it, you can read the [PDF](http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf) of this sensor. To run this example, you should have one ESP development board (e.g. ESP32-WROVER Kit) or ESP core board (e.g. ESP32-DevKitC). Optionally, you can also connect an external sensor. Here we choose the BH1750 just as an example. BH1750 is a digital ambient light sensor. For more information about it, you can read the [datasheet](http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf) of this sensor.
#### Pin Assignment: #### Pin Assignment(esp32, esp32s2):
**Note:** The following pin assignments are used by default, yout can change these in the `menuconfig` . **Note:** The following pin assignments are used by default, yout can change these in the `menuconfig` .
| | SDA | SCL | | | SDA | SCL |
| ---------------- | ------ | ------ | | ------------------------- | ------ | ------ |
| ESP32 I2C Master | GPIO18 | GPIO19 | | ESP32/ESP32-S2 I2C Master | GPIO18 | GPIO19 |
| ESP32 I2C Slave | GPIO4 | GPIO5 | | ESP32/ESP32-S2 I2C Slave | GPIO4 | GPIO5 |
| BH1750 Sensor | SDA | SCL | | BH1750 Sensor | SDA | SCL |
- slave: - slave:
- GPIO4 is assigned as the data signal of I2C slave port - GPIO4 is assigned as the data signal of I2C slave port
@ -39,7 +39,25 @@ To run this example, you should have one ESP32 dev board (e.g. ESP32-WROVER Kit)
- connect GPIO19 with GPIO5 - connect GPIO19 with GPIO5
- connect SDA/SCL of BH1750 sensor with GPIO18/GPIO19 - connect SDA/SCL of BH1750 sensor with GPIO18/GPIO19
**Note: ** Theres no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors. **Note:** It is recommended to add external pull-up resistors for SDA/SCL pins to make the communication more stable, though the driver will enable internal pull-up resistors.
#### Pin Assignment(esp32c3):
**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` .
| | SDA | SCL |
| ------------------------- | ------ | ------ |
| ESP32-C3 I2C Master(Slave)| GPIO5 | GPIO6 |
| BH1750 Sensor | SDA | SCL |
- master:
- GPIO5 is assigned to the data signal of the I2C master port
- GPIO6 is assigned to the clock signal of the I2C master port
- Connection:
- connect SDA/SCL of BH1750 sensor to GPIO5/GPIO6
**Note:** There is only one i2c device on esp32c3, so you can't try any master-slave example for esp32/s2 in this repo. But you can try external devices. If you find anything wrong with your device, please try connecting pull-up resistors by yourself.
### Configure the project ### Configure the project

View File

@ -3,19 +3,22 @@ menu "Example Configuration"
menu "I2C Master" menu "I2C Master"
config I2C_MASTER_SCL config I2C_MASTER_SCL
int "SCL GPIO Num" int "SCL GPIO Num"
default 19 default 6 if IDF_TARGET_ESP32C3
default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help help
GPIO number for I2C Master clock line. GPIO number for I2C Master clock line.
config I2C_MASTER_SDA config I2C_MASTER_SDA
int "SDA GPIO Num" int "SDA GPIO Num"
default 18 default 5 if IDF_TARGET_ESP32C3
default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
help help
GPIO number for I2C Master data line. GPIO number for I2C Master data line.
config I2C_MASTER_PORT_NUM config I2C_MASTER_PORT_NUM
int "Port Number" int "Port Number"
default 1 default 1 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
default 0 if IDF_TARGET_ESP32C3
help help
Port number for I2C Master device. Port number for I2C Master device.

View File

@ -58,8 +58,9 @@ SemaphoreHandle_t print_mux = NULL;
* | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop | * | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop |
* --------|--------------------------|----------------------|--------------------|------| * --------|--------------------------|----------------------|--------------------|------|
* *
* @note cannot use master read slave on esp32c3 because there is only one i2c controller on esp32c3
*/ */
static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size) static esp_err_t __attribute__((unused)) i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size)
{ {
if (size == 0) { if (size == 0) {
return ESP_OK; return ESP_OK;
@ -87,8 +88,9 @@ static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, siz
* | start | slave_addr + wr_bit + ack | write n bytes + ack | stop | * | start | slave_addr + wr_bit + ack | write n bytes + ack | stop |
* --------|---------------------------|----------------------|------| * --------|---------------------------|----------------------|------|
* *
* @note cannot use master write slave on esp32c3 because there is only one i2c controller on esp32c3
*/ */
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size) static esp_err_t __attribute__((unused)) 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_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd); i2c_master_start(cmd);
@ -160,6 +162,7 @@ static esp_err_t i2c_master_init(void)
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
} }
#if !CONFIG_IDF_TARGET_ESP32C3
/** /**
* @brief i2c slave initialization * @brief i2c slave initialization
*/ */
@ -196,15 +199,18 @@ static void disp_buf(uint8_t *buf, int len)
} }
printf("\n"); printf("\n");
} }
#endif //!CONFIG_IDF_TARGET_ESP32C3
static void i2c_test_task(void *arg) static void i2c_test_task(void *arg)
{ {
int i = 0;
int ret; int ret;
uint32_t task_idx = (uint32_t)arg; uint32_t task_idx = (uint32_t)arg;
#if !CONFIG_IDF_TARGET_ESP32C3
int i = 0;
uint8_t *data = (uint8_t *)malloc(DATA_LENGTH); uint8_t *data = (uint8_t *)malloc(DATA_LENGTH);
uint8_t *data_wr = (uint8_t *)malloc(DATA_LENGTH); uint8_t *data_wr = (uint8_t *)malloc(DATA_LENGTH);
uint8_t *data_rd = (uint8_t *)malloc(DATA_LENGTH); uint8_t *data_rd = (uint8_t *)malloc(DATA_LENGTH);
#endif //!CONFIG_IDF_TARGET_ESP32C3
uint8_t sensor_data_h, sensor_data_l; uint8_t sensor_data_h, sensor_data_l;
int cnt = 0; int cnt = 0;
while (1) { while (1) {
@ -226,6 +232,7 @@ static void i2c_test_task(void *arg)
xSemaphoreGive(print_mux); xSemaphoreGive(print_mux);
vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS); vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS);
//--------------------------------------------------- //---------------------------------------------------
#if !CONFIG_IDF_TARGET_ESP32C3
for (i = 0; i < DATA_LENGTH; i++) { for (i = 0; i < DATA_LENGTH; i++) {
data[i] = i; data[i] = i;
} }
@ -281,6 +288,7 @@ static void i2c_test_task(void *arg)
} }
xSemaphoreGive(print_mux); xSemaphoreGive(print_mux);
vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS); vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS);
#endif //!CONFIG_IDF_TARGET_ESP32C3
} }
vSemaphoreDelete(print_mux); vSemaphoreDelete(print_mux);
vTaskDelete(NULL); vTaskDelete(NULL);
@ -289,7 +297,9 @@ static void i2c_test_task(void *arg)
void app_main(void) void app_main(void)
{ {
print_mux = xSemaphoreCreateMutex(); print_mux = xSemaphoreCreateMutex();
#if !CONFIG_IDF_TARGET_ESP32C3
ESP_ERROR_CHECK(i2c_slave_init()); ESP_ERROR_CHECK(i2c_slave_init());
#endif
ESP_ERROR_CHECK(i2c_master_init()); ESP_ERROR_CHECK(i2c_master_init());
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void *)0, 10, NULL); xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void *)0, 10, NULL);
xTaskCreate(i2c_test_task, "i2c_test_task_1", 1024 * 2, (void *)1, 10, NULL); xTaskCreate(i2c_test_task, "i2c_test_task_1", 1024 * 2, (void *)1, 10, NULL);