I2C EEPROM Чтение / запись Cubieboard 2 Arch Linux

Я пытаюсь читать и писать в EEPROM AT24MAC402 через i2c на Cubieboard 2 с помощью Arch Linux. Я использую библиотеку i2c-dev и i2c-tools.

Лист данных: http://www.atmel.com/images/atmel-8807-seeprom-at24mac402-602-datasheet.pdf

Я могу успешно писать (вроде ...) на выбранный адрес и последовательно записывать много битов, начиная с этого адреса. Проблемы следующие:

  1. Невозможно повторно выбрать другой адрес для записи после выбора первого адреса.
  2. Невозможно указать EEPROM в том месте, откуда я хочу читать (фиктивная запись), и поэтому практически не имею реального контроля над EEPROM.

Глядя на таблицу (часами подряд), кажется, что у меня нет такого контроля над связью I2C, который мне может понадобиться с помощью библиотеки i2c-dev. Было бы здорово, если бы я мог просто написать X бит или X байтов напрямую в EEPROM.

Короче говоря, я хотел бы получить совет о том, как я могу правильно читать и писать в эту EEPROM.

    char buf[10];

    int com_serial;
    int failcount;

    int i2c_init(char filename[40], int addr)
        {
        int file;

        if ((file = open(filename,O_RDWR)) < 0)
                {
                printf("Failed to open the bus.");
                /* ERROR HANDLING; you can check errno to see what went wrong */
                com_serial=0;
                exit(1);
                }

    if (ioctl(file,I2C_SLAVE,addr) < 0)
                {
                printf("Failed to acquire bus access and/or talk to slave.\n");
                /* ERROR HANDLING; you can check errno to see what went wrong */
                com_serial=0;
                exit(1);
                }
        return file;
        }


    int main (int argc, char *argv[]) { 

    char read_buf[16];
    char write_buf[17];
    int i;

    int file;
    file=i2c_init("/dev/i2c-1",0x50); //dev,slavei2caddr
    write_buf[0] = 0x00;
    write_buf[1] = 'H';
    write_buf[2] = 'i';
    write_buf[3] = '!';
    write(file, write_buf, 4);
    //Successfully prints "Hi!" to bytes 0x00 -> 0x02

    //Setting EEPROM to point to address 0xA0 to start reading (arbitrary address with known values: all 0xFF)
    write_buf[0] = 0xA0;    
    write(file, write_buf, 1);

    //Reading 1 byte from EEPROM, even though there is a '2'; 2 bytes would be '3'
    read(file, read_buf, 2);

    for (i=1; i<3; i++){
        printf("%X", read_buf[i]);
    }
    //Prints out from address 0x04 to 0x05 instead of 0xA0 to 0xA1

    printf("\n");

    }

person StuartKerr    schedule 12.06.2014    source источник


Ответы (1)


Я работал правильно, используя функции из linux / i2c-dev.h.

Чтобы проверить код, я получаю вывод, сгенерированный i2cdump, и помещаю его в качестве ввода в инструмент i2c-stub-from-dump, он позволяет вам установить один или несколько поддельных чипов I2C на шине i2c-stub на основе дампов чипов, которые вы хотите подражать.

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>

int i2c_init(const char * i2c_device, const int chip_address)
{
    int file;
    if ((file = open(i2c_device, O_RDWR)) < 0) {
        return -1;
    }
    if (ioctl(file, I2C_SLAVE, chip_address) < 0) {
        close(file);
        return -1;
    }
    return file;
}

int i2c_write(int file, const int data_address, const unsigned char * data, size_t size)
{
    return i2c_smbus_write_i2c_block_data(file, data_address, size, data);
}

void i2c_read(int file, const int data_address, unsigned char * data_vector, size_t size)
{
    unsigned char reg = data_address;
    unsigned int i;
    for(i = 0; i < size; ++i, ++reg) {
        data_vector[i] = i2c_smbus_read_byte_data(file, reg);
    }
}

int main(void) {

    char device[] = "/dev/i2c-6";
    int address = 0x50;
    unsigned char buffer_before[30] = {0};
    unsigned char buffer_after[30] = {0};
    unsigned char data[] = "Hello World!"; 

    int file;
    file = i2c_init(device, address);

    if (file > 0) {
        i2c_read(file, 0x00, buffer_before, sizeof(data)); 
        i2c_write(file, 0x00, data, sizeof(data)); 
        i2c_read(file, 0x00, buffer_after, sizeof(data)); 
        close (file);
    }

    printf("data read before write: %s\n", buffer_before);
    printf("data read after write: %s\n", buffer_after);
    return 0;
}
person Rafael De Lucena Valle    schedule 28.05.2015