ESP32 操作AT24C32或AT24C64

  • AT24C32或AT24C64两款芯片容量不一样,其他都一样。程序无法动态识别容量
  • AT24C32容量32K,地址范围0x~0x7FFF.
  • AT24C64容量64K,地址范围0x~0xFFFF

电气参数

  • 电压2.7V-5.5V

  • IIC通信

  • 有引脚控制数据保护

  • 有引脚可以配置IIC的地址。
    在这里插入图片描述

  • 每个page 32字节

  • 1百万次写入

  • 100年存放

  • 容量有两个型号AT24C32/64 提供32,768/65,536 bits ,也就是4096字节(4k字节)或8192字节(8K字节)

  • 使用16bit来确定存储的地址

  • 设备地址,如果引脚A0~A2都接地,则IIC地址为0x50.

操作步骤

写入
分为两种

  • 按字节写入
  • 按page写入,一次最多写入32字节

读取
分为3种

  • 当前地址读取
  • 随机地址读取
  • 连续读取,连续读取可以一直读

EEPROM和flash有个最大的区别:
EEPROM在写入前不需要擦除page,直接写入就行
Flash 在写入前,需要擦除,且擦除是按照page进行的。比如spi flash。

时序

写入时序
按1个字节写入时序
在这里插入图片描述按page写入时序
在这里插入图片描述在这里插入图片描述

读取时序
在当前位置读取时序
在这里插入图片描述随机读取时序
在这里插入图片描述顺序读取时序
在这里插入图片描述
在这里插入图片描述

附上完整代码

AT24CXX_driver.c

#include <stdio.h>
#include "esp_log.h"
#include "AT24CXX_driver.h"
#include "driver/i2c.h"
#include <string.h>

static const char *TAG = "AT24CXX-driver";

#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM 0                        /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 100000               /*!< 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 I2C_MASTER_TIMEOUT_MS 1000

#define AT24CXX_I2C_ADDR 0x50 /*!< Slave address of the MPU9250 sensor */

esp_err_t at24cxx_init(void)
{
    int ret;

    // 初始化iic
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    ret = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);

    ESP_LOGI(TAG, "I2C initialized successfully");

    return ret;
}

/**
 * 读取当前位置的数据
 */
esp_err_t at24cxx_read_current(uint8_t *data, uint32_t len)
{
    int ret;

    // 开始读取数据
    ret = i2c_master_read_from_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    ESP_LOGI(TAG, "READ current DATA:");
    for (uint32_t i = 0; i < len; i++)
    {
        printf("%x ", data[i]);
    }

    return ret;
}

/**
 * 随机读取一个字节
 *
 */
esp_err_t at24cxx_random_read_byte(uint16_t address, uint8_t *data)
{
    int ret;
    uint8_t write_buf[2] = {address >> 8, address & 0xff};

    // 开始读取数据
    ret = i2c_master_write_read_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2,
                                       data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    ESP_LOGI(TAG, "at24cxx_random_read_byte:%x", *data);

    return ret;
}

/**
 * 随机读取一个字节
 *
 */
esp_err_t at24cxx_random_read(uint16_t address, uint8_t *data, uint32_t len)
{
    int ret;

    if (len == 0)
    {
        return 0;
    }

    // 开始读取数据

    at24cxx_random_read_byte(address, data);
    vTaskDelay(30 / portTICK_PERIOD_MS);

    if (len > 1)
    {
        at24cxx_read_current(data + 1, len - 1);
    }

    ESP_LOGI(TAG, "random READ DATA:");
    for (uint32_t i = 0; i < len; i++)
    {
        printf("%x ", data[i]);
    }

    return ret;
}

void at24cxx_dump(void)
{
    uint8_t data[4096], write_buf[2] = {0, 0};

    // 开始读取数据
    i2c_master_write_read_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2,
                                 data, 4096, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    ESP_LOGI(TAG, "READ DATA:");
    printf("   ");
    for (uint8_t i = 0; i < 16; i++)
    {
        printf("%2x ", i);
    }

    printf("\r\n00 ");
    for (uint32_t i = 0; i < 4096; i++)
    {
        printf("%2x ", data[i]);
        if (((i + 1) % 16 == 0) && (i != 0))
        {
            printf("\r\n%2lx ", i / 16);
        }
    }
}

/**
 * @brief 按字节写入
 */
esp_err_t at24cxx_write_byte(uint16_t address, uint8_t data)
{
    int ret = 0;
    uint8_t write_buf[3] = {address >> 8, address & 0xFF, data};

    ret = i2c_master_write_to_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 3, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
}

/**
 * @brief 按字节写入
 * @param page_index 第几个page
 */
esp_err_t at24cxx_write_page(uint16_t page_index, at24c_page pg)
{
    int ret = 0;
    // 算出page对应的地址
    uint16_t address = page_index * 32;

    uint8_t write_buf[2 + 32] = {address >> 8, address & 0xFF};

    memcpy(write_buf + 2, &pg, 32);

    ret = i2c_master_write_to_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2 + 32, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);

    return ret;
}

AT24CXX_driver.h

#ifndef __DS1307_H_
#define __DS1307_H_

#include "driver/i2c.h"

typedef struct
{
    union
    {
        uint8_t value[32];
        uint32_t value_32[32 / 4];
    };
} at24c_page; // 秒

esp_err_t at24cxx_init(void);
esp_err_t at24cxx_write_byte(uint16_t address, uint8_t data);
esp_err_t at24cxx_write_page(uint16_t page_index, at24c_page pg);
esp_err_t at24cxx_read_current(uint8_t *data, uint32_t len);
esp_err_t at24cxx_random_read_byte(uint16_t address, uint8_t *data);
esp_err_t at24cxx_random_read(uint16_t address, uint8_t *data, uint32_t len);
void at24cxx_dump(void);

#endif

AT24CXX_main.c

#include <stdio.h>
#include "esp_log.h"
#include "AT24CXX_driver.h"

static const char *TAG = "AT24CXX_main";

void app_main(void)
{

    at24c_page pg;
    uint8_t eeprom_data[10], *p = (uint8_t *)&pg;

    ESP_ERROR_CHECK(at24cxx_init());

    /* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */

    for (uint8_t i = 0; i < 32; i++)
    {
        p[i] = i;
    }

    ESP_LOGI(TAG, "test at24cxx_write_byte");
    at24cxx_write_byte(9,0xAA);//在下标9的地址处写入数据0xAA
    ESP_LOGI(TAG, "test at24cxx_write_page");
    at24cxx_write_page(1, pg);
    vTaskDelay(300 / portTICK_PERIOD_MS);

    //这个函数可能会造成爆栈,主要是里面有个很大的数组。实际代码要优化这个位置,比如边读变输出,或使用动态内存
    // at24cxx_dump();

    ESP_LOGI(TAG, "test at24cxx_read_current");
    ESP_ERROR_CHECK(at24cxx_read_current(eeprom_data, 10));

    ESP_LOGI(TAG, "test at24cxx_random_read");

    ESP_ERROR_CHECK(at24cxx_random_read(1,eeprom_data,5));

    ESP_LOGI(TAG, "test finish");
}

i2cget -c 0x50 -r 0 -l 10

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值