This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I2C address read problem


#include <stdio.h>
#include <stdlib.h>

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

void main()
{
    int fd,i;
    int addr = 0b10100000;        // The I2C address of the ADC
    char buf[10] = {0};
    float data;
    char channel;


    if ((fd = open("/dev/i2c-4",O_RDWR | O_WRONLY | O_NDELAY )) < 0)
    {
        printf("Failed to open the bus.");
        exit(1);
    }

    if (ioctl(fd,I2C_SLAVE,addr) < 0)
    {
        printf("Failed to acquire bus access and/or talk to slave.\n");
        exit(1);
    }

    buf[0] = 0b00000000;

    if (write(fd,buf,1) != 1)
        {
            printf("Failed to write to the i2c bus.\n");
            printf("\n\n");
        }

    buf[0] = 0b00000000;

    if (write(fd,buf,1) != 1)
        {
            printf("Failed to write to the i2c bus.\n");
            printf("\n\n");
        }
/*    buf[0] = 0x00;

    if (write(fd,buf,1) != 1)
        {
            printf("Failed to write to the i2c bus.\n");
            printf("\n\n");
        }
    buf[0] = 0x00;

    if (write(fd,buf,1) != 1)
        {
            printf("Failed to write to the i2c bus.\n");
            printf("\n\n");
        }
*/
    buf[0] = 0b11111111;

    if (write(fd,buf,1) != 1)
        {
            printf("Failed to write to the i2c bus.\n");
            printf("\n\n");
        }


    if (read(fd,buf,1) != 1)
    {
            printf("Failed to read from the i2c bus.\n");
    }
    else
    {
        //data = (float)((buf[0] & 0b00001111)<<8)+buf[1];
            //data = data/4096*5;
          //  channel = ((buf[0] & 0b00110000)>>4);
            printf("value read=%c",buf[0]);
    }

/*
    for(i = 0; i<4; i++)
    {
        if (read(fd,buf,2) != 2)
        {
                printf("Failed to read from the i2c bus.\n");
        }
        else
        {
            data = (float)((buf[0] & 0b00001111)<<8)+buf[1];
                data = data/4096*5;
              //  channel = ((buf[0] & 0b00110000)>>4);
              //  printf("Channel %02d Data:  %04f\n",channel,data);
        }
    }
*/
 

        
}
This is my i2c program to write the data on to the EEPROM 24c64. but the address of eeprom is not detected by this and there is show the error as below

"Failed to acquire bus access and/or talk to slave."

So Please guide me to solved the problem.

Thnks In advanse.

  • Just a guess. Try a 7 bit address rather than an 8 bit. Use 0b01010000 instead of 0b10100000.

  • i have to work with EEPROM 24c64.

    My Device Address is  8 bit and this is as below

    bit number  7      6       5      4      3       2        1         0

                         1       0      1      0     A2     A1     A0     R/W

    Here  i have grond the A2, A1, A0 and i want to right the data on 0x00 location so R/w is 0.

    so my address is 1010 0000

    so how can convert this address in 7bit address?

    Please help me and check my code and give suggestion if  require.

    Thanks.

  • This my connection diagram .

    Please check this and give suggestion if require.

    Thanks  in advance

    After set the 7 bit address(0b01010000) there is error as below.

    Failed to read from the i2c bus.                                                
    Failed to read from the i2c bus.                                                
    Failed to read from the i2c bus.                                                
    Failed to read from the i2c bus.                                                
    Failed to write to the i2c bus.

  • I'm more firmware than hardware. I do not know if that circuit will work. The pull-up resistors seem a bit low. You should connect up a scope to check out the signals on both 1.8V and 5V domains. With such strong pullups, your signal may not fall quick enough. Hopefully more knowledgable people will comment.

    Your program output does not appear to match the code in your first post. From a high level perspective, what are you trying to do? Are you trying to write a byte? Are you trying to set the current address? Are you trying to do a current address read operation?

    Note that each read() and write() calls will generate a complete I2C transaction with Start, Address, R/W, Data, Stop. If you need a repeated start operation, you will have to use a ioctl() call.

  • Thanks For your Answer.

    I can't understand your answer.

    I have to check that my hardware is OK.but I think that there is problem in code.

    I want to write the 0xff on the 0000 address of above EEPROM.

    so please check my code and please tell me what is wrong.

    if possible please give me code for that.

    Thanks & advance.

  • The datasheet for the 24c64 states that a byte write transaction consists of a 2 byte address and a data byte. Your code does write 3 bytes but it does this as three separate transactions. To send all three bytes as one transaction like so:

    buf[0] = 0x00; /*Most Sigificant Byte of Address */
    buf[1] = 0x00; /*Least Sigificant Byte of Address */
    buf[2] = 0xFF; /*Data*/
    write(fd,buf,3);

    Note that a write can take 5ms to complete. A write or read immediately after a write will fail.


  • #include <stdio.h>
    #include <stdlib.h>

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


    void Delay(unsigned int sec)
    {
        unsigned int i,j;
        for(j=0;j<sec;j++)
        for(i=0;i<=50000;i++);
    }
    int main()
    {
        int fd,i;
        int addr = 0b01010000 ;        // The I2C address of the ADC
        char buf[10] = {0};
        float data;
        char channel;


        if ((fd = open("/dev/i2c-4",O_RDWR | O_WRONLY | O_NDELAY )) < 0)
        {
            printf("Failed to open the bus.");
            exit(1);
        }

        Delay(10);

        if (ioctl(fd,I2C_SLAVE,addr) < 0)
        {
            printf("Failed to acquire bus access and/or talk to slave.\n");
            exit(1);
        }

        Delay(10);

        buf[0] = 0x00; /*Most Sigificant Byte of Address */
        buf[1] = 0x00; /*Least Sigificant Byte of Address */
        buf[2] = 0xFF; /*Data*/
        //write(fd,buf,3);

        if (write(fd,buf,3) != 3)
            {
                printf("Failed to write to the i2c bus.\n");
                printf("\n\n");
            exit(1);
            }
        close(fd);
        return 0;
    }

    This is my Code And after run on the Pandaboard ES.

    After run on board there is error as below

    " Failed to write to the i2c bus. "

    i think my address is wrong .

    i currently use the 24c64 EEPROM and it's 8 bit device address is as above explained so how i translate into 7 bit.



  • The Linux i2c driver expects 7-bit slave addresses but the data is still 8-bits. There is no translation required. Using a slave address of 0x50 is correct.

    You do not have to use your Delay() function after open() and ioctl(). In any case, your Delay() function may get optimized out. Use the library function usleep() instead after write().

    You could print out errno after the write() failure. That might give some hint as to what went wrong. Your code should work. I strongly suggest you look at the i2c lines on an oscilloscope. Make sure you see the activity as stated in the datasheet.

    Are you sure that the i2c-4 lines are pinmuxed to external pins? Is this an EVM? Is this a custom board? Which processor?

    EDIT: Did not see the Pandaboard ES note. I'm not familar with this board. I don't know if i2c-4 is enabled by default.

  • 1. The pullups are definitely too strong. Usually they are in kohms.

    2. make sure the i2c-4 bus you are using is enabled and muxed properly in your kernel.

    3. use a scope to observe the i2c traffic, this is essential when you try to debug something like this. You have to get your hands dirty on issues like this.

    4. Linux already has a driver for generic eeprom like yours, why don't you use that?

  • i have try all but there is not success by me so i have try new two codes are as Below.

    1) Write.c               //======this is the code for wrire the value on any address.

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    //#include <linux/i2c-dev.h>
    #include "i2c-dev.h"
    #include <fcntl.h>
    int main()
    {
        int fd;

        unsigned int val;

        if ((fd = open("/dev/i2c-4",O_RDWR | O_WRONLY | O_NDELAY )) < 0)
        {
            printf("ERROR1: %s\n", strerror(errno));
            exit(1);
        }

        if (ioctl(fd,I2C_SLAVE,0x50) < 0)
        {
            printf("ERROR2: %s\n", strerror(errno));
            exit(1);
        }


        if((val = i2c_smbus_write_byte_data(fd,0x05,0x55)) < 0 )
        {
            printf("ERROR3: %s\n", strerror(errno));
            exit(1);
        }

        close(fd);
        return 0;    
    }

    2) read.c   // this is the code for read the value from any address

    #include <stdio.h>
    #include <stdlib.h>
    //#include <linux/i2c-dev.h>
    #include "i2c-dev.h"
    #include <fcntl.h>
    #include <errno.h>

    int main()
    {
        int fd,val;
        
        if ((fd = open("/dev/i2c-4",O_RDWR | O_WRONLY | O_NDELAY )) < 0)
        {
            printf("ERROR1: %s\n", strerror(errno));
            exit(1);
        }

        if (ioctl(fd,I2C_SLAVE,0x50) < 0)
        {
            printf("ERROR2: %s\n", strerror(errno));
            exit(1);
        }

        if((val = i2c_smbus_read_byte_data(fd,0x05)) < 0 )
        {
            printf("ERROR3: %s\n", strerror(errno));
            exit(1);
        }
        
        printf("value= %d \n",val);    

        close(fd);
        return 0;
    }

    and its output as below

    shell@android:/data/local # ./write                                             
    shell@android:/data/local # ./read                                              
    value= 255                       

    There is no any error but there is little  fault to write the value on any address. so i am read the value but not write the value.

    i think my problem is how to give the 4 bit address by above function.

    So please help me to solve this proble.

    Thanks in Advance.

  • I've never used the smbus functuons. From what I can see in SM Bus doc, the SM Bus Protocol does not match protocol in the 24C64 datasheet. The SM Bus uses one byte commands that don't match the EEPROM's two byte addresses. Even if your HW is good, I doubt that the smbus functions will work properly. Good luck.

  • Hello,

    I never used the i2c on Linux so please tell me what I am do .

    Please give me the little small code which can write 1 address and read address.

    There is "i2c-4" is used in the

    Thanks In Advance.

  • You use of ioctl is wrong.

    Try this piece of code:

    static int i2c_debug = 0;

    //==========================================================================

    int
    i2c_read(unsigned char addr, unsigned char* cmd, int cmd_len,
        unsigned char* data, int data_len)
    {

      int result, fd;
      struct i2c_msg msg[2] =
        {
          { .addr = addr, .flags = 0, .buf = cmd, .len = cmd_len },
          { .addr = addr, .flags = I2C_M_RD, .buf = data, .len = data_len }, };
      struct i2c_rdwr_ioctl_data ioctl_data =
        { .msgs = msg, .nmsgs = 2 };

      if (cmd_len<=0 || data_len <= 0)
        return -1;

      fd = open("/dev/i2c-4", O_RDWR);
      if (fd < 0)
        {
          fprintf(stderr, "I2C: Failed to open device.\r\n");
          return -1;
        }
      result = ioctl(fd, I2C_RDWR, &ioctl_data);

      if (result < 0 && i2c_debug)
        {
          fprintf(stderr,
              "%s: I2C Read Failed: %s, addr=0x%02x cmd=0x",
              get_curr_time(), strerror(errno), addr);
          int i;
          for(i=0;i<cmd_len;i++)
            {
              fprintf(stderr,"%02X",cmd[i]);
            }
          fprintf(stderr,"read_len=%d\r\n",data_len);
        }

      if (i2c_debug > 3 && (result >= 0))
        {
          int i;
          printf("========= I2C READ ========\r\n");
          for (i = 0; i < data_len; i++)
            {
              printf("%02X ", data[i]);
              if ((i % 16) == 15)
                fprintf(stdout, "\r\n");
            }
          printf("\r\n");
        }
      close(fd);
      return result;
    }

    //==========================================================================
    int
    i2c_write(unsigned char addr, unsigned char* buffer, int len)
    {

      int result, fd;
      struct i2c_msg msg[1] =
        {
          { .addr = addr, .flags = 0, .buf = buffer, .len = len }, };

      struct i2c_rdwr_ioctl_data ioctl_data =
        { .msgs = msg, .nmsgs = 0x01 };

      if (len <= 0)
        return -1;
      fd = open("/dev/i2c-4", O_RDWR);
      if (fd < 0)
        {
          fprintf(stderr, "I2C: Failed to open device.\r\n");
          return -1;
        }
      result = ioctl(fd, I2C_RDWR, &ioctl_data);

      if (result < 0 && i2c_debug)
        {
          fprintf(stderr,
              "%s: I2C Write Failed: %s, addr=0x%02x cmd=0x%02x, write_len=%d\r\n",
              get_curr_time(), strerror(errno), addr, buffer[0], len);
        }
      close(fd);

      return result;
    }
    //==========================================================================