From 89d7f7bc89d55379990f384a73ce9052d4872500 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 8 Oct 2018 16:50:26 +0800 Subject: [PATCH] doc/i2c-example: cleanup readme of i2c example 1. Update i2c README to add more detail according to the template.[TW#26530] 2. Move some specific configuration to KConfig --- examples/peripherals/i2c/README.md | 29 -- .../i2c/{ => i2c_self_test}/CMakeLists.txt | 2 +- .../i2c/{ => i2c_self_test}/Makefile | 2 +- .../peripherals/i2c/i2c_self_test/README.md | 152 +++++++++ .../{ => i2c_self_test}/main/CMakeLists.txt | 0 .../i2c/i2c_self_test/main/Kconfig.projbuild | 124 +++++++ .../i2c/{ => i2c_self_test}/main/component.mk | 0 .../i2c/i2c_self_test/main/i2c_example_main.c | 291 ++++++++++++++++ .../peripherals/i2c/main/i2c_example_main.c | 312 ------------------ 9 files changed, 569 insertions(+), 343 deletions(-) delete mode 100644 examples/peripherals/i2c/README.md rename examples/peripherals/i2c/{ => i2c_self_test}/CMakeLists.txt (91%) rename examples/peripherals/i2c/{ => i2c_self_test}/Makefile (84%) create mode 100644 examples/peripherals/i2c/i2c_self_test/README.md rename examples/peripherals/i2c/{ => i2c_self_test}/main/CMakeLists.txt (100%) create mode 100644 examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild rename examples/peripherals/i2c/{ => i2c_self_test}/main/component.mk (100%) create mode 100644 examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c delete mode 100644 examples/peripherals/i2c/main/i2c_example_main.c diff --git a/examples/peripherals/i2c/README.md b/examples/peripherals/i2c/README.md deleted file mode 100644 index 7a88894bf1..0000000000 --- a/examples/peripherals/i2c/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# I2C Example - - -* This example will show you how to use I2C module by running two tasks on i2c bus: - - * read external i2c sensor, here we use a BH1750 light sensor(GY-30 module) for instance. - * Use one I2C port(master mode) to read or write the other I2C port(slave mode) on one ESP32 chip. - -* Pin assignment: - - * slave : - * GPIO25 is assigned as the data signal of i2c slave port - * GPIO26 is assigned as the clock signal of i2c slave port - * master: - * GPIO18 is assigned as the data signal of i2c master port - * GPIO19 is assigned as the clock signal of i2c master port - -* Connection: - - * connect GPIO18 with GPIO25 - * connect GPIO19 with GPIO26 - * connect sda/scl of sensor with GPIO18/GPIO19 - * no need to add external pull-up resistors, driver will enable internal pull-up resistors. - -* Test items: - - * read the sensor data, if connected. - * i2c master(ESP32) will write data to i2c slave(ESP32). - * i2c master(ESP32) will read data from i2c slave(ESP32). diff --git a/examples/peripherals/i2c/CMakeLists.txt b/examples/peripherals/i2c/i2c_self_test/CMakeLists.txt similarity index 91% rename from examples/peripherals/i2c/CMakeLists.txt rename to examples/peripherals/i2c/i2c_self_test/CMakeLists.txt index 1db34db220..498971710e 100644 --- a/examples/peripherals/i2c/CMakeLists.txt +++ b/examples/peripherals/i2c/i2c_self_test/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(i2c) +project(i2c-example) diff --git a/examples/peripherals/i2c/Makefile b/examples/peripherals/i2c/i2c_self_test/Makefile similarity index 84% rename from examples/peripherals/i2c/Makefile rename to examples/peripherals/i2c/i2c_self_test/Makefile index d575e29b9d..8f64567bf1 100644 --- a/examples/peripherals/i2c/Makefile +++ b/examples/peripherals/i2c/i2c_self_test/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -PROJECT_NAME := i2c +PROJECT_NAME := i2c-example include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/i2c/i2c_self_test/README.md b/examples/peripherals/i2c/i2c_self_test/README.md new file mode 100644 index 0000000000..499b35e3c0 --- /dev/null +++ b/examples/peripherals/i2c/i2c_self_test/README.md @@ -0,0 +1,152 @@ +# I2C Self-Test Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## Overview + +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. +2. Use one of ESP32’s I2C port (master mode) to read and write another I2C port (slave mode) in ESP32. + +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. + +## How to use example + +### 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. + +#### Pin Assignment: + +**Note:** The following pin assignments are used by default, yout can change these in the `menuconfig` . + +| | SDA | SCL | +| ---------------- | ------ | ------ | +| ESP32 I2C Master | GPIO18 | GPIO19 | +| ESP32 I2C Slave | GPIO25 | GPIO26 | +| BH1750 Sensor | SDA | SCL | + +- slave: + - GPIO25 is assigned as the data signal of I2C slave port + - GPIO26 is assigned as the clock signal of I2C slave port +- master: + - GPIO18 is assigned as the data signal of I2C master port + - GPIO19 is assigned as the clock signal of I2C master port + +- Connection: + - connect GPIO18 with GPIO25 + - connect GPIO19 with GPIO26 + - connect SDA/SCL of BH1750 sensor with GPIO18/GPIO19 + +**Note: ** There’s no need to add an external pull-up resistors for SDA/SCL pin, because the driver will enable the internal pull-up resistors. + +### Configure the project + +Enter `make menuconfig` if you are using GNU Make based build system or enter `idf.py menuconfig` if you are using CMake based build system. Then go into `Example Configuration` menu. + +- In the `I2C Master` submenu, you can set the pin number of SDA/SCL according to your board. Also you can modify the I2C port number and freauency of the master. +- In the `I2C Slave` submenu, you can set the pin number of SDA/SCL according to your board. Also you can modify the I2C port number and address of the slave. +- In the `BH1750 Sensor` submenu, you can choose the slave address of BH1750 accroding to the pin level of ADDR pin (if the pin level of ADDR is low then the address is `0x23`, otherwise it is `0x5c`). Here you can also control the operation mode of BH1750, each mode has a different resolution and measurement time. For example, in the `One Time L-Resolution` mode, the resolution is 4 Lux and measurement time is typically 16ms (higher resolution means longer measurement time). For more information, you can consult the datasheet of BH1750. + + +### Build and Flash + +Enter `make -j4 flash monitor` if you are using GNU Make based build system or enter `idf.py build flash monitor` if you' are using CMake based build system. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +```bash +I (6495) i2c-example: TASK[1] test cnt: 1 +******************* +TASK[1] MASTER READ SENSOR( BH1750 ) +******************* +data_h: 01 +data_l: d0 +sensor val: 386.67 [Lux] +I (6695) i2c-example: TASK[0] test cnt: 2 +******************* +TASK[0] MASTER READ SENSOR( BH1750 ) +******************* +data_h: 01 +data_l: d0 +sensor val: 386.67 [Lux] +******************* +TASK[0] MASTER READ FROM SLAVE +******************* +====TASK[0] Slave buffer data ==== +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f +30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f +50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f +60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f +70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f + +====TASK[0] Master read ==== +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f +30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f +50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f +60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f +70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f + +******************* +TASK[1] MASTER READ FROM SLAVE +******************* +====TASK[1] Slave buffer data ==== +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f +30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f +50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f +60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f +70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f + +====TASK[1] Master read ==== +00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f +20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f +30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f +40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f +50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f +60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f +70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f + +******************* +TASK[0] MASTER WRITE TO SLAVE +******************* +----TASK[0] Master write ---- +0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 +1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 +2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 +3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 +4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 +5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 +6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 +7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 + +----TASK[0] Slave read: [128] bytes ---- +0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 +1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 +2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 +3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 +4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 +5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 +6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 +7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 +``` + +## Troubleshooting + +- BH1750 has two I2C address, which is decided by the voltage level of `ADDR` pin at start up. Make sure to check your schemetic before run this example. + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/peripherals/i2c/main/CMakeLists.txt b/examples/peripherals/i2c/i2c_self_test/main/CMakeLists.txt similarity index 100% rename from examples/peripherals/i2c/main/CMakeLists.txt rename to examples/peripherals/i2c/i2c_self_test/main/CMakeLists.txt diff --git a/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild b/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild new file mode 100644 index 0000000000..0266b3e60d --- /dev/null +++ b/examples/peripherals/i2c/i2c_self_test/main/Kconfig.projbuild @@ -0,0 +1,124 @@ +menu "Example Configuration" + +menu "I2C Master" + config I2C_MASTER_SCL + int "SCL GPIO Num" + default 19 + help + GPIO number for I2C Master clock line. + +config I2C_MASTER_SDA + int "SDA GPIO Num" + default 18 + help + GPIO number for I2C Master data line. + +config I2C_MASTER_PORT_NUM + int "Port Number" + default 1 + help + Port number for I2C Master device. + +config I2C_MASTER_FREQUENCY + int "Master Frequency" + default 100000 + help + I2C Speed of Master device. +endmenu + +menu "I2C Slave" + config I2C_SLAVE_SCL + int "SCL GPIO Num" + default 26 + help + GPIO number for I2C Slave clock line. + +config I2C_SLAVE_SDA + int "SDA GPIO Num" + default 25 + help + GPIO number for I2C Slave data line. + +config I2C_SLAVE_PORT_NUM + int "Port Number" + default 0 + help + Port number for I2C Slave device. + +config I2C_SLAVE_ADDRESS + hex "ESP Slave Address" + default 0x28 + help + Hardware Address of I2C Slave Port. +endmenu + +menu "BH1750 Sensor" +choice BH1750_ADDR + prompt "BH1750 I2C Address" + default BH1750_I2C_ADDRESS_LOW + help + Hardware address of BH1750, which is 2 types, and determined by ADDR terminal. + +config BH1750_I2C_ADDRESS_LOW + bool "BH1750 I2C Address(ADDR=0)" + help + I2C Address of BH1750 Sensor according to your schemetic configuration. + +config BH1750_I2C_ADDRESS_High + bool "BH1750 I2C Address(ADDR=1)" + help + I2C Address of BH1750 Sensor according to your schemetic configuration. +endchoice + +config BH1750_ADDR + hex + default 0x5C if BH1750_I2C_ADDRESS_High + default 0x23 if BH1750_I2C_ADDRESS_LOW + +choice BH1750_MODE + prompt "BH1750 Operation Mode" + default BH1750_ONETIME_L_RESOLUTION + help + Operation Mode of BH1750. + Different mode means different resolution and measurement time. +config BH1750_CONTINU_H_RESOLUTION + bool "Continuously H-Resolution Mode" + help + Resolution is 1lx, measurement time is typically 120ms. +config BH1750_CONTINU_H_RESOLUTION2 + bool "Continuously H-Resolution Mode2" + help + Resolution is 0.5lx, measurement time is typically 120ms. +config BH1750_CONTINU_L_RESOLUTION + bool "Continuously L-Resolution Mode" + help + Resolution is 4lx, measurement time is typically 16ms. +config BH1750_ONETIME_H_RESOLUTION + bool "One Time H-Resolution Mode" + help + Resolution is 1lx, measurement time is typically 120ms. + It is automatically set to Power Down mode after measurement. +config BH1750_ONETIME_H_RESOLUTION2 + bool "One Time H-Resolution Mode2" + help + Resolution is 0.5lx, measurement time is typically 120ms. + It is automatically set to Power Down mode after measurement. +config BH1750_ONETIME_L_RESOLUTION + bool "One Time L-Resolution Mode" + help + Resolution is 4lx, measurement time is typically 16ms. + It is automatically set to Power Down mode after measurement. +endchoice + +config BH1750_OPMODE + hex + default 0x10 if BH1750_CONTINU_H_RESOLUTION + default 0x11 if BH1750_CONTINU_H_RESOLUTION2 + default 0x13 if BH1750_CONTINU_L_RESOLUTION + default 0x20 if BH1750_ONETIME_H_RESOLUTION + default 0x21 if BH1750_ONETIME_H_RESOLUTION2 + default 0x23 if BH1750_ONETIME_L_RESOLUTION + +endmenu + +endmenu diff --git a/examples/peripherals/i2c/main/component.mk b/examples/peripherals/i2c/i2c_self_test/main/component.mk similarity index 100% rename from examples/peripherals/i2c/main/component.mk rename to examples/peripherals/i2c/i2c_self_test/main/component.mk diff --git a/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c b/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c new file mode 100644 index 0000000000..9b108a9aa6 --- /dev/null +++ b/examples/peripherals/i2c/i2c_self_test/main/i2c_example_main.c @@ -0,0 +1,291 @@ +/* i2c - Example + + For other examples please check: + https://github.com/espressif/esp-idf/tree/master/examples + + See README.md file to get detailed usage of this example. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "esp_log.h" +#include "driver/i2c.h" +#include "sdkconfig.h" + +static const char *TAG = "i2c-example"; + +#define _I2C_NUMBER(num) I2C_NUM_##num +#define I2C_NUMBER(num) _I2C_NUMBER(num) + +#define DATA_LENGTH 512 /*!< Data buffer length of test buffer */ +#define RW_TEST_LENGTH 128 /*!< Data length for r/w test, [0,DATA_LENGTH] */ +#define DELAY_TIME_BETWEEN_ITEMS_MS 1000 /*!< delay time between different test items */ + +#define I2C_SLAVE_SCL_IO CONFIG_I2C_SLAVE_SCL /*!< gpio number for i2c slave clock */ +#define I2C_SLAVE_SDA_IO CONFIG_I2C_SLAVE_SDA /*!< gpio number for i2c slave data */ +#define I2C_SLAVE_NUM I2C_NUMBER(CONFIG_I2C_SLAVE_PORT_NUM) /*!< I2C port number for slave dev */ +#define I2C_SLAVE_TX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave tx buffer size */ +#define I2C_SLAVE_RX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave rx buffer size */ + +#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< gpio number for I2C master clock */ +#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< gpio number for I2C master data */ +#define I2C_MASTER_NUM I2C_NUMBER(CONFIG_I2C_MASTER_PORT_NUM) /*!< I2C port number for master dev */ +#define I2C_MASTER_FREQ_HZ CONFIG_I2C_MASTER_FREQUENCY /*!< 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 BH1750_SENSOR_ADDR CONFIG_BH1750_ADDR /*!< slave address for BH1750 sensor */ +#define BH1750_CMD_START CONFIG_BH1750_OPMODE /*!< Operation mode */ +#define ESP_SLAVE_ADDR CONFIG_I2C_SLAVE_ADDRESS /*!< ESP32 slave address, you can set any 7bit value */ +#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ +#define READ_BIT I2C_MASTER_READ /*!< I2C master read */ +#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ +#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ +#define ACK_VAL 0x0 /*!< I2C ack value */ +#define NACK_VAL 0x1 /*!< I2C nack value */ + +SemaphoreHandle_t print_mux = NULL; + +/** + * @brief test code to read esp-i2c-slave + * We need to fill the buffer of esp slave device, then master can read them out. + * + * _______________________________________________________________________________________ + * | start | slave_addr + rd_bit +ack | read n-1 bytes + ack | read 1 byte + nack | stop | + * --------|--------------------------|----------------------|--------------------|------| + * + */ +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; +} + +/** + * @brief Test code to write esp-i2c-slave + * Master device write data to slave(both esp32), + * the data will be stored in slave buffer. + * We can read them out from slave buffer. + * + * ___________________________________________________________________ + * | start | slave_addr + wr_bit + ack | write n bytes + ack | stop | + * --------|---------------------------|----------------------|------| + * + */ +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 test code to operate on BH1750 sensor + * + * 1. set operation mode(e.g One time L-resolution mode) + * _________________________________________________________________ + * | start | slave_addr + wr_bit + ack | write 1 byte + ack | stop | + * --------|---------------------------|---------------------|------| + * 2. wait more than 24 ms + * 3. read data + * ______________________________________________________________________________________ + * | start | slave_addr + rd_bit + ack | read 1 byte + ack | read 1 byte + nack | stop | + * --------|---------------------------|--------------------|--------------------|------| + */ +static esp_err_t i2c_master_sensor_test(i2c_port_t i2c_num, uint8_t *data_h, uint8_t *data_l) +{ + int ret; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if (ret != ESP_OK) { + return ret; + } + vTaskDelay(30 / portTICK_RATE_MS); + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN); + i2c_master_read_byte(cmd, data_h, ACK_VAL); + i2c_master_read_byte(cmd, data_l, NACK_VAL); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + return ret; +} + +/** + * @brief i2c master initialization + */ +static esp_err_t i2c_master_init() +{ + int i2c_master_port = I2C_MASTER_NUM; + i2c_config_t conf; + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = I2C_MASTER_SDA_IO; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_io_num = I2C_MASTER_SCL_IO; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.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); +} + +/** + * @brief i2c slave initialization + */ +static esp_err_t i2c_slave_init() +{ + int i2c_slave_port = I2C_SLAVE_NUM; + i2c_config_t conf_slave; + conf_slave.sda_io_num = I2C_SLAVE_SDA_IO; + conf_slave.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf_slave.scl_io_num = I2C_SLAVE_SCL_IO; + conf_slave.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf_slave.mode = I2C_MODE_SLAVE; + conf_slave.slave.addr_10bit_en = 0; + conf_slave.slave.slave_addr = ESP_SLAVE_ADDR; + i2c_param_config(i2c_slave_port, &conf_slave); + return i2c_driver_install(i2c_slave_port, conf_slave.mode, + I2C_SLAVE_RX_BUF_LEN, + I2C_SLAVE_TX_BUF_LEN, 0); +} + +/** + * @brief test function to show buffer + */ +static void disp_buf(uint8_t *buf, int len) +{ + int i; + for (i = 0; i < len; i++) { + printf("%02x ", buf[i]); + if ((i + 1) % 16 == 0) { + printf("\n"); + } + } + printf("\n"); +} + +static void i2c_test_task(void *arg) +{ + int i = 0; + int ret; + uint32_t task_idx = (uint32_t)arg; + uint8_t *data = (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 sensor_data_h, sensor_data_l; + int cnt = 0; + while (1) { + ESP_LOGI(TAG, "TASK[%d] test cnt: %d", task_idx, cnt++); + ret = i2c_master_sensor_test(I2C_MASTER_NUM, &sensor_data_h, &sensor_data_l); + xSemaphoreTake(print_mux, portMAX_DELAY); + if (ret == ESP_ERR_TIMEOUT) { + ESP_LOGE(TAG, "I2C Timeout"); + } else if (ret == ESP_OK) { + printf("*******************\n"); + printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx); + printf("*******************\n"); + printf("data_h: %02x\n", sensor_data_h); + printf("data_l: %02x\n", sensor_data_l); + printf("sensor val: %.02f [Lux]\n", (sensor_data_h << 8 | sensor_data_l) / 1.2); + } else { + ESP_LOGW(TAG, "%s: No ack, sensor not connected...skip...", esp_err_to_name(ret)); + } + xSemaphoreGive(print_mux); + vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS); + //--------------------------------------------------- + for (i = 0; i < DATA_LENGTH; i++) { + data[i] = i; + } + xSemaphoreTake(print_mux, portMAX_DELAY); + size_t d_size = i2c_slave_write_buffer(I2C_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS); + if (d_size == 0) { + ESP_LOGW(TAG, "i2c slave tx buffer full"); + ret = i2c_master_read_slave(I2C_MASTER_NUM, data_rd, DATA_LENGTH); + } else { + ret = i2c_master_read_slave(I2C_MASTER_NUM, data_rd, RW_TEST_LENGTH); + } + + if (ret == ESP_ERR_TIMEOUT) { + ESP_LOGE(TAG, "I2C Timeout"); + } else if (ret == ESP_OK) { + printf("*******************\n"); + printf("TASK[%d] MASTER READ FROM SLAVE\n", task_idx); + printf("*******************\n"); + printf("====TASK[%d] Slave buffer data ====\n", task_idx); + disp_buf(data, d_size); + printf("====TASK[%d] Master read ====\n", task_idx); + disp_buf(data_rd, d_size); + } else { + ESP_LOGW(TAG, "TASK[%d] %s: Master read slave error, IO not connected...\n", + task_idx, esp_err_to_name(ret)); + } + xSemaphoreGive(print_mux); + vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS); + //--------------------------------------------------- + int size; + for (i = 0; i < DATA_LENGTH; i++) { + data_wr[i] = i + 10; + } + xSemaphoreTake(print_mux, portMAX_DELAY); + //we need to fill the slave buffer so that master can read later + ret = i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH); + if (ret == ESP_OK) { + size = i2c_slave_read_buffer(I2C_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS); + } + if (ret == ESP_ERR_TIMEOUT) { + ESP_LOGE(TAG, "I2C Timeout"); + } else if (ret == ESP_OK) { + printf("*******************\n"); + printf("TASK[%d] MASTER WRITE TO SLAVE\n", task_idx); + printf("*******************\n"); + printf("----TASK[%d] Master write ----\n", task_idx); + disp_buf(data_wr, RW_TEST_LENGTH); + printf("----TASK[%d] Slave read: [%d] bytes ----\n", task_idx, size); + disp_buf(data, size); + } else { + ESP_LOGW(TAG, "TASK[%d] %s: Master write slave error, IO not connected....\n", + task_idx, esp_err_to_name(ret)); + } + xSemaphoreGive(print_mux); + vTaskDelay((DELAY_TIME_BETWEEN_ITEMS_MS * (task_idx + 1)) / portTICK_RATE_MS); + } + vSemaphoreDelete(print_mux); + vTaskDelete(NULL); +} + +void app_main() +{ + print_mux = xSemaphoreCreateMutex(); + ESP_ERROR_CHECK(i2c_slave_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_1", 1024 * 2, (void *)1, 10, NULL); +} diff --git a/examples/peripherals/i2c/main/i2c_example_main.c b/examples/peripherals/i2c/main/i2c_example_main.c deleted file mode 100644 index e887355f0b..0000000000 --- a/examples/peripherals/i2c/main/i2c_example_main.c +++ /dev/null @@ -1,312 +0,0 @@ -/* i2c - Example - - For other examples please check: - https://github.com/espressif/esp-idf/tree/master/examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include "driver/i2c.h" - -/** - * TEST CODE BRIEF - * - * This example will show you how to use I2C module by running two tasks on i2c bus: - * - * - read external i2c sensor, here we use a BH1750 light sensor(GY-30 module) for instance. - * - Use one I2C port(master mode) to read or write the other I2C port(slave mode) on one ESP32 chip. - * - * Pin assignment: - * - * - slave : - * GPIO25 is assigned as the data signal of i2c slave port - * GPIO26 is assigned as the clock signal of i2c slave port - * - master: - * GPIO18 is assigned as the data signal of i2c master port - * GPIO19 is assigned as the clock signal of i2c master port - * - * Connection: - * - * - connect GPIO18 with GPIO25 - * - connect GPIO19 with GPIO26 - * - connect sda/scl of sensor with GPIO18/GPIO19 - * - no need to add external pull-up resistors, driver will enable internal pull-up resistors. - * - * Test items: - * - * - read the sensor data, if connected. - * - i2c master(ESP32) will write data to i2c slave(ESP32). - * - i2c master(ESP32) will read data from i2c slave(ESP32). - */ - -#define DATA_LENGTH 512 /*! 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; -} - -/** - * @brief Test code to write esp-i2c-slave - * Master device write data to slave(both esp32), - * the data will be stored in slave buffer. - * We can read them out from slave buffer. - * - * ___________________________________________________________________ - * | start | slave_addr + wr_bit + ack | write n bytes + ack | stop | - * --------|---------------------------|----------------------|------| - * - */ -static esp_err_t i2c_example_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 test code to write esp-i2c-slave - * - * 1. set mode - * _________________________________________________________________ - * | start | slave_addr + wr_bit + ack | write 1 byte + ack | stop | - * --------|---------------------------|---------------------|------| - * 2. wait more than 24 ms - * 3. read data - * ______________________________________________________________________________________ - * | start | slave_addr + rd_bit + ack | read 1 byte + ack | read 1 byte + nack | stop | - * --------|---------------------------|--------------------|--------------------|------| - */ -static esp_err_t i2c_example_master_sensor_test(i2c_port_t i2c_num, uint8_t* data_h, uint8_t* data_l) -{ - int ret; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if (ret != ESP_OK) { - return ret; - } - vTaskDelay(30 / portTICK_RATE_MS); - cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN); - i2c_master_read_byte(cmd, data_h, ACK_VAL); - i2c_master_read_byte(cmd, data_l, NACK_VAL); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - return ret; -} - -/** - * @brief i2c master initialization - */ -static void i2c_example_master_init() -{ - int i2c_master_port = I2C_EXAMPLE_MASTER_NUM; - i2c_config_t conf; - conf.mode = I2C_MODE_MASTER; - conf.sda_io_num = I2C_EXAMPLE_MASTER_SDA_IO; - conf.sda_pullup_en = GPIO_PULLUP_ENABLE; - conf.scl_io_num = I2C_EXAMPLE_MASTER_SCL_IO; - conf.scl_pullup_en = GPIO_PULLUP_ENABLE; - conf.master.clk_speed = I2C_EXAMPLE_MASTER_FREQ_HZ; - i2c_param_config(i2c_master_port, &conf); - i2c_driver_install(i2c_master_port, conf.mode, - I2C_EXAMPLE_MASTER_RX_BUF_DISABLE, - I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0); -} - -/** - * @brief i2c slave initialization - */ -static void i2c_example_slave_init() -{ - int i2c_slave_port = I2C_EXAMPLE_SLAVE_NUM; - i2c_config_t conf_slave; - conf_slave.sda_io_num = I2C_EXAMPLE_SLAVE_SDA_IO; - conf_slave.sda_pullup_en = GPIO_PULLUP_ENABLE; - conf_slave.scl_io_num = I2C_EXAMPLE_SLAVE_SCL_IO; - conf_slave.scl_pullup_en = GPIO_PULLUP_ENABLE; - conf_slave.mode = I2C_MODE_SLAVE; - conf_slave.slave.addr_10bit_en = 0; - conf_slave.slave.slave_addr = ESP_SLAVE_ADDR; - i2c_param_config(i2c_slave_port, &conf_slave); - i2c_driver_install(i2c_slave_port, conf_slave.mode, - I2C_EXAMPLE_SLAVE_RX_BUF_LEN, - I2C_EXAMPLE_SLAVE_TX_BUF_LEN, 0); -} - -/** - * @brief test function to show buffer - */ -static void disp_buf(uint8_t* buf, int len) -{ - int i; - for (i = 0; i < len; i++) { - printf("%02x ", buf[i]); - if (( i + 1 ) % 16 == 0) { - printf("\n"); - } - } - printf("\n"); -} - -static void i2c_test_task(void* arg) -{ - int i = 0; - int ret; - uint32_t task_idx = (uint32_t) arg; - uint8_t* data = (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 sensor_data_h, sensor_data_l; - int cnt = 0; - while (1) { - printf("test cnt: %d\n", cnt++); - ret = i2c_example_master_sensor_test( I2C_EXAMPLE_MASTER_NUM, &sensor_data_h, &sensor_data_l); - xSemaphoreTake(print_mux, portMAX_DELAY); - if(ret == ESP_ERR_TIMEOUT) { - printf("I2C timeout\n"); - } else if(ret == ESP_OK) { - printf("*******************\n"); - printf("TASK[%d] MASTER READ SENSOR( BH1750 )\n", task_idx); - printf("*******************\n"); - printf("data_h: %02x\n", sensor_data_h); - printf("data_l: %02x\n", sensor_data_l); - printf("sensor val: %f\n", (sensor_data_h << 8 | sensor_data_l) / 1.2); - } else { - printf("%s: No ack, sensor not connected...skip...\n", esp_err_to_name(ret)); - } - xSemaphoreGive(print_mux); - vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS); - //--------------------------------------------------- - for (i = 0; i < DATA_LENGTH; i++) { - data[i] = i; - } - xSemaphoreTake(print_mux, portMAX_DELAY); - size_t d_size = i2c_slave_write_buffer(I2C_EXAMPLE_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS); - if (d_size == 0) { - printf("i2c slave tx buffer full\n"); - ret = i2c_example_master_read_slave(I2C_EXAMPLE_MASTER_NUM, data_rd, DATA_LENGTH); - } else { - ret = i2c_example_master_read_slave(I2C_EXAMPLE_MASTER_NUM, data_rd, RW_TEST_LENGTH); - } - - if (ret == ESP_ERR_TIMEOUT) { - printf("I2C timeout\n"); - printf("*********\n"); - } else if (ret == ESP_OK) { - printf("*******************\n"); - printf("TASK[%d] MASTER READ FROM SLAVE\n", task_idx); - printf("*******************\n"); - printf("====TASK[%d] Slave buffer data ====\n", task_idx); - disp_buf(data, d_size); - printf("====TASK[%d] Master read ====\n", task_idx); - disp_buf(data_rd, d_size); - } else { - printf("%s: Master read slave error, IO not connected...\n", esp_err_to_name(ret)); - } - xSemaphoreGive(print_mux); - vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS); - //--------------------------------------------------- - int size; - for (i = 0; i < DATA_LENGTH; i++) { - data_wr[i] = i + 10; - } - xSemaphoreTake(print_mux, portMAX_DELAY); - //we need to fill the slave buffer so that master can read later - ret = i2c_example_master_write_slave( I2C_EXAMPLE_MASTER_NUM, data_wr, RW_TEST_LENGTH); - if (ret == ESP_OK) { - size = i2c_slave_read_buffer( I2C_EXAMPLE_SLAVE_NUM, data, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS); - } - if (ret == ESP_ERR_TIMEOUT) { - printf("I2C timeout\n"); - } else if (ret == ESP_OK) { - printf("*******************\n"); - printf("TASK[%d] MASTER WRITE TO SLAVE\n", task_idx); - printf("*******************\n"); - printf("----TASK[%d] Master write ----\n", task_idx); - disp_buf(data_wr, RW_TEST_LENGTH); - printf("----TASK[%d] Slave read: [%d] bytes ----\n", task_idx, size); - disp_buf(data, size); - } else { - printf("TASK[%d] %s: Master write slave error, IO not connected....\n", task_idx, esp_err_to_name(ret)); - } - xSemaphoreGive(print_mux); - vTaskDelay(( DELAY_TIME_BETWEEN_ITEMS_MS * ( task_idx + 1 ) ) / portTICK_RATE_MS); - } -} - -void app_main() -{ - print_mux = xSemaphoreCreateMutex(); - i2c_example_slave_init(); - i2c_example_master_init(); - 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); - -} -