mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(i2c_eeprom): Add new example for I2C eeprom with new API
This commit is contained in:
parent
b6cbeeae01
commit
d9d1c87e56
6
examples/peripherals/i2c/i2c_eeprom/CMakeLists.txt
Normal file
6
examples/peripherals/i2c/i2c_eeprom/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(i2c_eeprom)
|
54
examples/peripherals/i2c/i2c_eeprom/README.md
Normal file
54
examples/peripherals/i2c/i2c_eeprom/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# I2C EEPROM example
|
||||
|
||||
This code demonstrates how to use the I2C master mode to read/write I2C EEPROM.
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates basic usage of I2C driver by reading and writing from a I2C connected eeprom:
|
||||
|
||||
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, ESP32-S, ESP32-C or ESP32-H based development board as well as EEPROM(s). I2C bus allow use several EEPROMs, and some of the EEPROMs' address are configurable. Some are not, for which you can use 74LS138 to set different EEPROM different slave address(It is also can be used on other types of I2C slaves).
|
||||
|
||||
For some I2C EEPROM slaves, they have A0, A1, A2 pins for address configuration.
|
||||
For some I2C slaves, They don't have address configuration pins but have enable pins. For these kind of slave, you can use GPIO pins and external decoder to select which slave you are using.
|
||||
|
||||
#### Pin Assignment:
|
||||
|
||||
**Note:** The following pin assignments are used by default, you can change these in the `menuconfig` .
|
||||
|
||||
| | SDA | SCL |
|
||||
| ---------------- | -------------- | -------------- |
|
||||
| ESP I2C Master | I2C_MASTER_SDA | I2C_MASTER_SCL |
|
||||
| EEPROM1 | SDA | SCL |
|
||||
| EEPROMn | SDA | SCL |
|
||||
|
||||
For the actual default value of `I2C_MASTER_SDA` and `I2C_MASTER_SCL` see `Example Configuration` in `menuconfig`.
|
||||
|
||||
**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.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
|
||||
(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
|
||||
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
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
(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.)
|
@ -0,0 +1,3 @@
|
||||
idf_component_register(SRCS "i2c_eeprom.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES driver)
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "i2c_eeprom.h"
|
||||
#include "esp_check.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#define I2C_EEPROM_MAX_TRANS_UNIT (48)
|
||||
// Different EEPROM device might share one I2C bus
|
||||
|
||||
static const char TAG[] = "i2c-eeprom";
|
||||
|
||||
esp_err_t i2c_eeprom_init(i2c_master_bus_handle_t bus_handle, const i2c_eeprom_config_t *eeprom_config, i2c_eeprom_handle_t *eeprom_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
i2c_eeprom_handle_t out_handle;
|
||||
out_handle = (i2c_eeprom_handle_t)calloc(1, sizeof(i2c_eeprom_handle_t));
|
||||
ESP_GOTO_ON_FALSE(out_handle, ESP_ERR_NO_MEM, err, TAG, "no memory for i2c eeprom device");
|
||||
|
||||
i2c_device_config_t i2c_dev_conf = {
|
||||
.scl_speed_hz = eeprom_config->eeprom_device.scl_speed_hz,
|
||||
.device_address = eeprom_config->eeprom_device.device_address,
|
||||
};
|
||||
|
||||
if (out_handle->i2c_dev == NULL) {
|
||||
ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &out_handle->i2c_dev), err, TAG, "i2c new bus failed");
|
||||
}
|
||||
|
||||
out_handle->buffer = (uint8_t*)calloc(1, eeprom_config->addr_wordlen + I2C_EEPROM_MAX_TRANS_UNIT);
|
||||
out_handle->addr_wordlen = eeprom_config->addr_wordlen;
|
||||
out_handle->write_time_ms = eeprom_config->write_time_ms;
|
||||
*eeprom_handle = out_handle;
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (out_handle) {
|
||||
free(out_handle);
|
||||
}
|
||||
if (out_handle->i2c_dev) {
|
||||
i2c_master_bus_rm_device(out_handle->i2c_dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2c_eeprom_write(i2c_eeprom_handle_t eeprom_handle, uint32_t address, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
for (int i = 0; i < eeprom_handle->addr_wordlen; i++) {
|
||||
eeprom_handle->buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
|
||||
}
|
||||
|
||||
memcpy(eeprom_handle->buffer + eeprom_handle->addr_wordlen, data, size);
|
||||
ret = i2c_master_transmit(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen + size, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t i2c_eeprom_read(i2c_eeprom_handle_t eeprom_handle, uint32_t address, uint8_t *data, uint32_t size)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(eeprom_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
|
||||
esp_err_t ret = ESP_OK;
|
||||
for (int i = 0; i < eeprom_handle->addr_wordlen; i++) {
|
||||
eeprom_handle->buffer[i] = (address & (0xff << ((eeprom_handle->addr_wordlen - 1 - i) * 8))) >> ((eeprom_handle->addr_wordlen - 1 - i) * 8);
|
||||
}
|
||||
|
||||
ret = i2c_master_transmit_receive(eeprom_handle->i2c_dev, eeprom_handle->buffer, eeprom_handle->addr_wordlen, data, size, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void i2c_eeprom_wait_idle(i2c_eeprom_handle_t eeprom_handle)
|
||||
{
|
||||
// This is time for EEPROM Self-Timed Write Cycle
|
||||
vTaskDelay(pdMS_TO_TICKS(eeprom_handle->write_time_ms));
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
i2c_device_config_t eeprom_device; /*!< Configuration for eeprom device */
|
||||
uint8_t addr_wordlen; /*!< block address wordlen */
|
||||
uint8_t write_time_ms; /*!< eeprom write time, typically 10ms*/
|
||||
} i2c_eeprom_config_t;
|
||||
|
||||
struct i2c_eeprom_t {
|
||||
i2c_master_dev_handle_t i2c_dev; /*!< I2C device handle */
|
||||
uint8_t addr_wordlen; /*!< block address wordlen */
|
||||
uint8_t *buffer; /*!< I2C transaction buffer */
|
||||
uint8_t write_time_ms; /*!< I2C eeprom write time(ms)*/
|
||||
};
|
||||
|
||||
typedef struct i2c_eeprom_t i2c_eeprom_t;
|
||||
|
||||
/* handle of EEPROM device */
|
||||
typedef struct i2c_eeprom_t *i2c_eeprom_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Init an EEPROM device.
|
||||
*
|
||||
* @param[in] bus_handle I2C master bus handle
|
||||
* @param[in] eeprom_config Configuration of EEPROM
|
||||
* @param[out] eeprom_handle Handle of EEPROM
|
||||
* @return ESP_OK: Init success. ESP_FAIL: Not success.
|
||||
*/
|
||||
esp_err_t i2c_eeprom_init(i2c_master_bus_handle_t bus_handle, const i2c_eeprom_config_t *eeprom_config, i2c_eeprom_handle_t *eeprom_handle);
|
||||
|
||||
/**
|
||||
* @brief Write data to EEPROM
|
||||
*
|
||||
* @param[in] eeprom_handle EEPROM handle
|
||||
* @param[in] address Block address inside EEPROM
|
||||
* @param[in] data Data to write
|
||||
* @param[in] size Data write size
|
||||
* @return ESP_OK: Write success. Otherwise failed, please check I2C function fail reason.
|
||||
*/
|
||||
esp_err_t i2c_eeprom_write(i2c_eeprom_handle_t eeprom_handle, uint32_t address, const uint8_t *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Read data from EEPROM
|
||||
*
|
||||
* @param eeprom_handle EEPROM handle
|
||||
* @param address Block address inside EEPROM
|
||||
* @param data Data read from EEPROM
|
||||
* @param size Data read size
|
||||
* @return ESP_OK: Read success. Otherwise failed, please check I2C function fail reason.
|
||||
*/
|
||||
esp_err_t i2c_eeprom_read(i2c_eeprom_handle_t eeprom_handle, uint32_t address, uint8_t *data, uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Wait eeprom finish. Typically 5ms
|
||||
*
|
||||
* @param eeprom_handle EEPROM handle
|
||||
*/
|
||||
void i2c_eeprom_wait_idle(i2c_eeprom_handle_t eeprom_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
4
examples/peripherals/i2c/i2c_eeprom/main/CMakeLists.txt
Normal file
4
examples/peripherals/i2c/i2c_eeprom/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
set(srcs "i2c_eeprom_main.c")
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ".")
|
23
examples/peripherals/i2c/i2c_eeprom/main/Kconfig.projbuild
Normal file
23
examples/peripherals/i2c/i2c_eeprom/main/Kconfig.projbuild
Normal file
@ -0,0 +1,23 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
menu "I2C Master"
|
||||
config I2C_MASTER_SCL
|
||||
int "SCL GPIO Num"
|
||||
default 4
|
||||
help
|
||||
GPIO number for I2C Master clock line.
|
||||
|
||||
config I2C_MASTER_SDA
|
||||
int "SDA GPIO Num"
|
||||
default 5
|
||||
help
|
||||
GPIO number for I2C Master data line.
|
||||
|
||||
config I2C_MASTER_FREQUENCY
|
||||
int "Master Frequency"
|
||||
default 400000
|
||||
help
|
||||
I2C Speed of Master device.
|
||||
endmenu
|
||||
|
||||
endmenu
|
70
examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c
Normal file
70
examples/peripherals/i2c/i2c_eeprom/main/i2c_eeprom_main.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "i2c_eeprom.h"
|
||||
|
||||
#define SCL_IO_PIN CONFIG_I2C_MASTER_SCL
|
||||
#define SDA_IO_PIN CONFIG_I2C_MASTER_SDA
|
||||
#define MASTER_FREQUENCY CONFIG_I2C_MASTER_FREQUENCY
|
||||
#define PORT_NUMBER -1
|
||||
#define LENGTH 48
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
i2c_master_bus_config_t i2c_bus_config = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.i2c_port = PORT_NUMBER,
|
||||
.scl_io_num = SCL_IO_PIN,
|
||||
.sda_io_num = SDA_IO_PIN,
|
||||
};
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
|
||||
|
||||
i2c_eeprom_config_t eeprom_config = {
|
||||
.eeprom_device.scl_speed_hz = MASTER_FREQUENCY,
|
||||
.eeprom_device.device_address = 0x50,
|
||||
.addr_wordlen = 2,
|
||||
.write_time_ms = 10,
|
||||
};
|
||||
|
||||
i2c_eeprom_handle_t eeprom_handle;
|
||||
|
||||
uint32_t block_addr = 0x0010;
|
||||
uint8_t buf[LENGTH];
|
||||
for (int i = 0; i < LENGTH; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
uint8_t read_buf[LENGTH];
|
||||
ESP_ERROR_CHECK(i2c_eeprom_init(bus_handle, &eeprom_config, &eeprom_handle));
|
||||
|
||||
while(1) {
|
||||
ESP_ERROR_CHECK(i2c_eeprom_write(eeprom_handle, block_addr, buf, LENGTH));
|
||||
// Needs wait for eeprom hardware done, referring from datasheet
|
||||
i2c_eeprom_wait_idle(eeprom_handle);
|
||||
ESP_ERROR_CHECK(i2c_eeprom_read(eeprom_handle, block_addr, read_buf, LENGTH));
|
||||
disp_buf(read_buf, LENGTH);
|
||||
vTaskDelay(50);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user