当前位置: 首页 > news >正文

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);  // 将数据拷贝到缓冲区// 发送写入命令到 EEPROMesp_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};// 初始化 I2Ci2c_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);  //读地址0x7if (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");}}

 

 


http://www.mrgr.cn/news/41342.html

相关文章:

  • 【rCore OS 开源操作系统】Rust 练习题题解: Structs
  • 微调学习记录
  • 为什么有必要由母语人士翻译应用程序界面
  • HarmonyOS/OpenHarmony 自定义弹窗页面级层级控制解决方案
  • idea环境下vue2升级vue3
  • 绘制随k变化的等熵面积比公式
  • 【折半查找】
  • 体系结构论文(五十三):Featherweight Soft Error Resilience for GPUs 【22‘ MIRCO】
  • 栈和队列的相互实现(C)
  • QT系统学习篇(2)- Qt跨平台GUI原理机制
  • 【分别为微服务云原生】9分钟ActiveMQ延时消息队列:定时任务的革命与Quartz的较量
  • 主存储器——半导体芯片简介
  • 大数据实时数仓Hologres(三):存储格式介绍
  • Java 方法前面加 <T> 是做什么?泛型方法
  • 2025河南国际台球产业展览会,中国国际台球产业链发展大会
  • 【EXCEL数据处理】000010 案列 EXCEL文本型和常规型转换。使用的软件是微软的Excel操作的。处理数据的目的是让数据更直观的显示出来,方便查看。
  • 完全背包问题
  • 声纳技术24.1.19声纳定向方法
  • C++类和对象(上)
  • rtmp协议转websocketflv的去队列积压