Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

who can help me about I2C

http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/huh.gif

I &#39;m test the EEPROM of I2C interface,and meet a problem. I use the "opencores I2C master " module.

step 1, I write a byte, then read it, it&#39;s right.

step2, I write 8 bytes into the EEPROM, using step1

step3, I use "sequential read command "to continously read the data which been witen into eeprom by step2! Only the last byte is right, the bytes all are error before the last byte!

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    feiwu, What device are you writing to. 24C32 or similar?

    I am not familiar with the opencores i2c module, but I know I2c eeproms well.

    Are you allowing time between your write cycles. If you write your data in separate bus cycles (i.e. start-transactions-stop), then the device will detach itself from the I2C bus until it has completed its memory write cycle. You must wait until this is complete before writing the next byte. This can be done in 2 ways:

    1. pause or sleep for the manufactures maximum specified time period (typically around 10mS).

    2. attempt to address the device until it returns an acknowledge (called acknowledge polling).

    1 is the easiest to implement but 2 is more time efficient because the true time can be much less than the worst-case time.

    You can also write up to 32 bytes at once provided the address locations are all within the same page boundary (i.e. address bit 5 upwards are the same), but you must still perform the above wait afterwards.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Cliff,

    I&#39;m sorry, I&#39;m a fresher to the website!

    You understood me well, and I have added the address!

    But I only can read the last byte by "sequential read command "

    Where can I down load some cource code about I2C?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Can you provide some more detailed information?

    Are you able to determine how the module is accessing the I2c bus (e.g. start, read, write, stop sequences)

    Perhaps you could post a section of your code showing the problem.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    For the IP core ,you could download the NIOS2 linux1.3 , then set up the nios2linux 1.3 and you could see the IP core in SOPC builder!

    List is my soyurce code for test IIC , help me!

    I2C_prescale=ALT_CPU_FREQ/(5*100000)-1;//ALT_CPU_FREQ is in "system.h"

    IOWR(I2C_BASE,I2C_PRERlo,I2C_prescale);

    IOWR(I2C_BASE,I2C_PRERhi,I2C_prescale>>8); // high 8 bits

    PRERhi=IORD(I2C_BASE,I2C_PRERhi);//read again

    printf(" again PRERhi=%d\n",PRERhi);

    PRERlo=IORD(I2C_BASE,I2C_PRERlo);

    printf("again PRERlo=%d\n",PRERlo);

    //enable I2C

    CTR=IORD(I2C_BASE,I2C_CTR);

    printf("CTR=%2x\n",CTR);

    IOWR(I2C_BASE,I2C_CTR,0x80);

    CTR=IORD(I2C_BASE,I2C_CTR);

    printf("CTR=%2x\n",CTR);

    for(j=1;j<=8;j++)

    {

    printf("IIC test=%2x\n",j);

    //slect device

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf("1 CSR=%2x\n",CSR);

    IOWR(I2C_BASE,I2C_DATA,E2PROM_ADDR); //ob1010000 0 ,prepare the data first

    IOWR(I2C_BASE,I2C_CSR,0x91); //STA,WR,IACK ,start transferring

    //select memory

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02)

    printf("2 busy CSR=%2x\n",CSR) ; //tip=1 :when transferring data

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80)

    printf("3 no ack CSR=%2x\n",CSR) ; //rxack=0: Acknowledge received

    IOWR(I2C_BASE,I2C_DATA,eeprom_a+j);

    IOWR(I2C_BASE,I2C_CSR,0x11); //WR,IACK

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf("4 CSR=%2x\n",CSR);

    //write data and terminate

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02)

    printf("5 busy CSR=%2x\n",CSR) ; //tip=1

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80)

    printf("6 no ack CSR=%2x\n",CSR) ; //rxack=0

    //j=1;

    IOWR(I2C_BASE,I2C_DATA,eeprom_d+j);

    IOWR(I2C_BASE,I2C_CSR,0x51); //STO,WR,IACK

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02) //tip=1

    printf("7 busy CSR=%2x\n",CSR);

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80) //rxack=0

    printf("8 no ack CSR=%2x\n",CSR);

    i = 0;

    while (i<200000)

    i++;

    i = 0;

    while (i<200000)

    i++;

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf("9 CSR=%2x\n",CSR);

    ///////////////////////////////////////////////////////////////

    //read back

    /////////////////////////////////////

    //slect device COMMAND 1

    IOWR(I2C_BASE,I2C_DATA,E2PROM_ADDR);

    IOWR(I2C_BASE,I2C_CSR,0x91); //STA,WR,IACK

    //select memory

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    printf("10 CSR=%2x\n",CSR); //rxack=0

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0

    IOWR(I2C_BASE,I2C_DATA,eeprom_a+j-1);

    IOWR(I2C_BASE,I2C_CSR,0x11); //WR,IACK

    //select device and READ COMMAND 2

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0

    IOWR(I2C_BASE,I2C_DATA,E2PROM_ADDR+1); //device address and READ

    IOWR(I2C_BASE,I2C_CSR,0x91); //re-STA,WR,IACK

    //read data and terminate

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02) //tip=1

    {

    printf(" test1 CSR=%2x\n",CSR);

    }

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf(" test2 CSR=%2x\n",CSR);

    IOWR(I2C_BASE,I2C_CSR,0x21); //RD,ACK,IACK (0b0010 0001)

    while (i<50000)

    i++;

    Readdata_I2C_B=0x00;

    Readdata_I2C_B=IORD(I2C_BASE,I2C_DATA);

    printf(" Readdata_I2C_B=%2x\n",Readdata_I2C_B); //rxack=0

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    {

    printf(" test3 CSR=%2x\n",CSR); //rxack=0

    }

    //2005,07,20 shield

    //while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0 maybe not need the lopp

    //2005,07,20

    IOWR(I2C_BASE,I2C_CSR,0x69); //STO,RD,NACK,IACK (0b01101001)

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    // while((CSR=(I2C_BASE,I2C_CSR))&0x80)

    printf(" 11 CSR=%2x\n",CSR); //rxack=0

    Readdata_I2C=0x00;

    Readdata_I2C=IORD(I2C_BASE,I2C_DATA);

    if(Readdata_I2C==(eeprom_d+j))

    printf("write data= %2x Readdata_I2C=%2x\n OK\n!",eeprom_d+j,Readdata_I2C);

    else

    printf("write data= %2x Readdata_I2C=%2x\n ERROR!\n",eeprom_d+j,Readdata_I2C);

    i = 0;

    while (i<200000)

    i++;

    i = 0;

    while (i<200000)

    i++;

    } // Have been tested OK !

    // continuous read 8 bytes data by "sequential read " command

    printf(" IIC continously read test\n"); //rxack=0

    //slect device COMMAND 1

    IOWR(I2C_BASE,I2C_DATA,E2PROM_ADDR);

    IOWR(I2C_BASE,I2C_CSR,0x91); //STA,WR,IACK

    //select memory

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    printf("c1 CSR=%2x\n",CSR); //rxack=0

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0

    IOWR(I2C_BASE,I2C_DATA,eeprom_a); // from first address

    IOWR(I2C_BASE,I2C_CSR,0x11); //WR,IACK

    //select device and READ COMMAND 2

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0

    IOWR(I2C_BASE,I2C_DATA,E2PROM_ADDR+1); //device address and READ

    IOWR(I2C_BASE,I2C_CSR,0x91); //re-STA,WR,IACK

    //read data and terminate

    // prepare to get date

    // need judge ACK

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x80); //rxack=0

    for(j=1;j<=6;j++) // when I change the loop number, the last byte is always right

    {

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf(" C2 CSR=%2x\n",CSR);

    while(((CSR=IORD(I2C_BASE,I2C_CSR))&0x02)== 0x20) //tip=1

    {

    printf(" C3 CSR=%2x\n",CSR);

    }

    CSR=IORD(I2C_BASE,I2C_CSR);

    printf(" C4 CSR=%2x\n",CSR);

    IOWR(I2C_BASE,I2C_CSR,0x21); //ACK,IACK (0b0010 0001)

    Readdata_I2C_B=0x00;

    Readdata_I2C_B=IORD(I2C_BASE,I2C_DATA);

    printf(" data= %2x Readdata_I2C_B=%2x\n OK!",j,Readdata_I2C_B);

    } // read 6 bytes ,all is error

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02) //tip=1

    {

    printf(" C5 CSR=%2x\n",CSR); //rxack=0

    }

    IOWR(I2C_BASE,I2C_CSR,0x69); // STO,RD,NACK,IACK (0b01101001)

    while((CSR=IORD(I2C_BASE,I2C_CSR))&0x02); //tip=1

    printf(" C6 CSR=%2x\n",CSR); //rxack=0

    Readdata_I2C=0x00;

    Readdata_I2C=IORD(I2C_BASE,I2C_DATA); // the last byte is OK!

    printf("data = 8 Readdata_I2C=%2x\n OK!",Readdata_I2C);
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    feiwu,

    I cannot see anything obviously wrong with your code.

    What eeprom addresses are you writing to (your vaiable eeprom_a)?

    It is strange that you are getting correct results in the first section but not in the second. In fact, you are actually using sequential read in both sections. You are reading the address just before the one just written with an ACK, followed by the actual location with a NACK. The is perfectly valid.

    You appear to be only reading back 7 bytes in your second section.

    One comment I would make is that you are performing a long delay using a counting loop. Have you checked that this is actually giving sufficient delay, since clock speed, processor type and optimization level can effect this. After your write operation you must wait for about 10mS before attempting any further comms with your eeprom. You might want to consider using usleep(), since this will give a known delay.

    I may be worth looking at what is happening on the i2c pins using an oscilloscope or use Signal-Tap to analyse the real time activity.