You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用户态读取32k I2C EEPROM如何设置起始地址并实现i2cset等效功能

问题根因

I2C EEPROM内部维护了一个地址指针,每次读写操作后指针会自动向后偏移对应操作的字节数。你之前的代码没有主动设置该指针的初始值,所以每次程序运行时都会继承上一次操作结束后指针的位置,才会出现读取起始地址不固定的问题。
你用到的i2cset -y 4 0x50 0x00 0x00命令,本质就是向地址为0x50的EEPROM写入2字节的起始地址0x00 0x00,将设备内部的地址指针复位到存储空间的起始位置。

代码实现方案

只需要在设置好I2C从设备地址之后、进入读循环之前,主动写入2字节的起始地址即可,等效于你手动执行的i2cset命令。同时你原来的代码还存在两个可优化的问题:

  • dump_to_file函数中使用O_CREAT标志打开文件时,没有指定文件权限,会导致生成的文件权限异常
  • dump_to_file函数写完数据后没有关闭文件描述符,多次调用会出现文件描述符泄漏,还可能导致数据没有刷入磁盘

修改后的完整代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

#define READ_SIZE   (256)
#define NB_PAGES    (128)

void dump_to_file(const char *output_file_path,
          const uint8_t *buffer, const int buffer_length)
{
    // O_CREAT标志必须指定第三个参数为文件权限,这里设置为用户读写、其他用户只读
    int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT, 0644);
    if (output_file < 0) {
        printf("Failed opening output file %s\n", output_file_path);
        return;
    }

    write(output_file, buffer, buffer_length);
    // 写完主动关闭文件,避免文件描述符泄漏和数据缓存问题
    close(output_file);
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        printf("Usage: %s <output_file_path>\n", argv[0]);
        return 1;
    }

    /* got these values from i2cdetect */
    const char *i2c_device = "/dev/i2c-4";
    const int device_address = 0x50;

    /* open the i2c device file */
    int file = open(i2c_device, O_RDWR);
    if (file < 0) {
        printf("Failed opening %s\n", i2c_device);
        return 1;
    }

    if (ioctl(file, I2C_SLAVE, device_address) < 0) {
        printf("Failed addressing device at %02X\n", device_address);
        close(file);
        return 1;
    }

    // 等效于i2cset -y 4 0x50 0x00 0x00,写入16位起始地址0x0000
    uint8_t start_addr[] = {0x00, 0x00};
    if (write(file, start_addr, sizeof(start_addr)) != sizeof(start_addr)) {
        printf("Failed to set EEPROM start address\n");
        close(file);
        return 1;
    }

    int i = 0;
    for (i = 0; i < NB_PAGES; i++) {
        uint8_t buf[READ_SIZE] = {0};

        if (read(file, buf, READ_SIZE) != READ_SIZE) {
            printf("Failed reading at page %d\n", i);
            close(file);
            return 1;
        }

        dump_to_file(argv[1], buf, READ_SIZE);
    }

    close(file);
    printf("EEPROM dump completed, total size: %d bytes\n", READ_SIZE * NB_PAGES);

    return 0;
}

内容的提问来源于stack exchange,提问作者Zibri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:54:04