How to operate at24c32 by smbus in linux?

255 Views Asked by At

What if the EEPROM used is greater than 32K, such as at24c32, and the register address is 16bit? It seems that smbus only supports 8bit registers?

I can read 0xff, but the written content will return - 5, which fails. I want to know whether the kernel only supports 8-bit registers, but not 16 bit registers?

This is my code:

#include <fcntl.h>
#include <stdio.h>
#include <linux/i2c-dev.h>
#include <errno.h>
#include <stddef.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>

#define AT24C32_ADDR 0x53

__s32 i2c_smbus_access(int file, char read_write, __u8 command,
                       int size, union i2c_smbus_data* data)
{
    struct i2c_smbus_ioctl_data args;
    __s32 err;

    args.read_write = read_write;
    args.command = command;
    args.size = size;
    args.data = data;

    err = ioctl(file, I2C_SMBUS, &args);
    if (err == -1)
        err = -errno;
    return err;
}

__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
{
    union i2c_smbus_data data;
    data.byte = value;
    return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                            I2C_SMBUS_BYTE_DATA, &data);
}

__s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
    union i2c_smbus_data data;
    int err;

    err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
                           I2C_SMBUS_BYTE_DATA, &data);
    if (err < 0)
        return err;

    return 0x0FF & data.byte;
}

static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value)
{
    union i2c_smbus_data data;

    data.word = value;

    return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd,
                            I2C_SMBUS_WORD_DATA, &data);
}

static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd)
{
    union i2c_smbus_data data;
    int err;

    err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd,
                           I2C_SMBUS_WORD_DATA, &data);
    if (err < 0)
        return err;

    return data.word;
}

int set_slave_addr(int file, int address, int force)
{
    /* With force, let the user read from/write to the registers
       even when a driver is also running */
    if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {
        fprintf(stderr,
                "Error: Could not set address to 0x%02x: %s\n",
                address, strerror(errno));
        return -errno;
    }

    return 0;
}
0

There are 0 best solutions below