24C256 (i2c)指令及时序(代码含单个字节和整页字节的写入)

1. I2C 地址

  • I2C 地址:设备的 I2C 地址为 0x50(7 位地址),在写和读操作中使用时会左移一位并添加读/写标志。
    • 写操作0xA0
    • 读操作0xA1

2. 基本指令

a. 写入指令

  • 写命令(Write Command)
    • 格式(设备地址 << 1) | 0(例如 0xA0
    • 步骤
      1. 发送 START。
      2. 发送控制字节(写命令)。
      3. 发送 16 位内存地址(高字节和低字节)。
      4. 发送要写入的数据字节。
      5. 发送 STOP。

b. 读取指令

  • 读取命令(Read Command)
    • 格式(设备地址 << 1) | 1(例如 0xA1
    • 步骤
      1. 发送 START。
      2. 发送控制字节(写命令)。
      3. 发送 16 位内存地址(高字节和低字节)。
      4. 发送 START。
      5. 发送控制字节(读命令)。
      6. 读取数据字节。
      7. 发送 NACK(如果不再读取数据)。
      8. 发送 STOP。

3. 页面写入

  • 页面写入(Page Write):
    • 每个页面的大小为 64 字节,写入时不能跨越页面边界。
    • 格式和步骤与写入命令相同,写入的数据可以是 1 至 64 字节。
    • 24C256 具有 512 个页面,每个页面大小为 64 字节
    • 在使用 24C256 EEPROM 进行读写时,地址通常需要手动管理。每次写入或读取数据时,您需要指定开始地址。24C256 是一个 256Kb 的 EEPROM,其中每个地址存储 1 字节数据,地址范围从 0 到 32767(0x0000 到 0x7FFF)。
    • esp32 写页函数为:i2c_master_write_to_device()。

4. 状态和控制指令

  • 写保护(WP)
    • WP 引脚:用于启用或禁用写保护功能。
      • 连接到 Vcc:写保护开启。
    • 连接到 GND:写保护关闭。

       

#include "driver/i2c.h"
#include <stdio.h>
#include <string.h>
#define I2C_MASTER_SCL_IO 15              // SCL 引脚
#define I2C_MASTER_SDA_IO 21               // SDA 引脚
#define I2C_MASTER_FREQ_HZ 100000          // I2C 时钟频率
#define I2C_MASTER_PORT I2C_NUM_0          // I2C 端口
#define EEPROM_I2C_ADDRESS 0x50            // 24C256 I2C 地址

// I2C 初始化函数
void i2c_master_init() {
    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);
    i2c_driver_install(I2C_MASTER_PORT, conf.mode, 0, 0, 0);
}

// 向 24C256 写入一个字节
esp_err_t eeprom_write_byte(uint16_t mem_address, uint8_t data) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (EEPROM_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
    
    // 发送内存地址的高字节和低字节
    i2c_master_write_byte(cmd, (mem_address >> 8) & 0xFF, true);
    i2c_master_write_byte(cmd, mem_address & 0xFF, true);
    
    // 发送要写入的数据
    i2c_master_write_byte(cmd, data, true);
    
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_PORT, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    
    // EEPROM 写入完成后通常需要 5ms 延迟
    vTaskDelay(5 / portTICK_PERIOD_MS);
    
    return ret;
}

// 从 24C256 读取一个字节
esp_err_t eeprom_read_byte(uint16_t mem_address, uint8_t *data) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    
    // 发送写命令,设置内存地址指针
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (EEPROM_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, (mem_address >> 8) & 0xFF, true);
    i2c_master_write_byte(cmd, mem_address & 0xFF, true);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_PORT, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    
    if (ret != ESP_OK) {
        return ret;
    }
    
    // 读取数据
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (EEPROM_I2C_ADDRESS << 1) | I2C_MASTER_READ, true);
    i2c_master_read_byte(cmd, data, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(I2C_MASTER_PORT, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    
    return ret;
}
#define PAGE_SIZE 64        // 每页大小

// 写入一页数据到 EEPROM
void eeprom_write_page(uint16_t addr, uint8_t* data, size_t len) {
    // 确保写入长度不超过页面大小
    if (len > PAGE_SIZE) {
        len = PAGE_SIZE;  // 截断长度
    }
    
    uint8_t buffer[PAGE_SIZE + 2]; // 额外的两个字节用于存储地址
    buffer[0] = (addr >> 8) & 0xFF; // 地址高字节
    buffer[1] = addr & 0xFF;        // 地址低字节
    memcpy(&buffer[2], data, len);  // 将数据拷贝到缓冲区

    // 发送写入命令到 EEPROM
    esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_PORT,EEPROM_I2C_ADDRESS, buffer, len + 2, 1000 / portTICK_PERIOD_MS);
    if (ret == ESP_OK) {
        // 写入成功,等待写入完成(大约 5 毫秒)
        vTaskDelay(5 / portTICK_PERIOD_MS);
    } else {
        // 处理写入错误
    }
}


void app_main() {
	
	uint8_t data1[PAGE_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
    // 初始化 I2C
    i2c_master_init();
    
    uint8_t write_data = 0x5A;  // 要写入的数据
    uint16_t address = 0x65;    // 24C256 的地址 0x88

    // 向 EEPROM 写入数据
    esp_err_t ret = eeprom_write_byte(address, write_data);
	
    if (ret == ESP_OK) {
        printf("Data 0x%X written to EEPROM at address 0x%X\n", write_data, address);
    } else {
        printf("Error writing data to EEPROM\n");
    }
     vTaskDelay(10 / portTICK_PERIOD_MS);
    // 读取 EEPROM 中的数据
    uint8_t read_data = 0;
    ret = eeprom_read_byte(address, &read_data);
    if (ret == ESP_OK) {
        printf("Data 0x%X read from EEPROM at address 0x%X\n", read_data, address);
    } else {
        printf("Error reading data from EEPROM\n");
    }
	//写页
	 eeprom_write_page(0, data1, PAGE_SIZE);  //从地址0x0开始
	  vTaskDelay(10 / portTICK_PERIOD_MS);
	 
	  ret = eeprom_read_byte(7, &read_data);  //读地址0x7
    if (ret == ESP_OK) {
        printf("Data 0x%X read from EEPROM at address 0x%X\n", read_data,7);
    } else {
        printf("Error reading data from EEPROM\n");
    }
	 
	
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值