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.

TMS570LS3137 - I2C programming

Other Parts Discussed in Thread: PCF8575, HALCOGEN, TMS570LS3137

Zhaohong,

While playing I2C interface write to and read from I2C device PCF8575 (TI, I/O expansion), I am running into some issue. Hope to get some advice from you.

(1) Write data to PCF8575.  Below code can successfull write data to PCF8675.  But it has two byte "delay" after the salve address is sent out, so I have to write two dummy bytes following the data bytes that expected to write.

My question: Why I have to use two dummy byte write to "push" the data "55" and "FF" out?

  I2CMDR_bit.nIRS =0;

   // prescale and Baud rate setting here */

  // mode control set below  

    I2CMDR_bit.NACKMOD = 0;  //send ACK out    

     I2CMDR_bit.STB = 0;     // not start byte

    I2CMDR_bit.MST =1;     //master

   I2CMDR_bit.TRX = 1;     //transmit

   I2CMDR_bit.RM = 1;     // repeate mode

   I2CMDR_bit.DLB = 0;      // no loop-back

   I2CMDR_bit.FREE = 0;    // free run

   I2CMDR_bit.FDF = 1;   // '1'=free data; '0'= Slave address at front

 

   I2CMDR_bit.nIRS = 1;   // out of reset

  I2CMDR_bit.STT = 1;  // start to send

 i2cSendByte(i2cREG1, 0x40); // Send Addr 0x40 and R/W=0     - i2cSendByte() just checks and waits TXRDY=1, send write data to I2CDXR

i2cSendByte(i2cREG1, 0x55); // Send first byte "55"   

i2cSendByte(i2cREG1, 0xFF); // Send 2nd byte "FF"

  i2cSendByte(i2cREG1, 0x00); // 1st byte dummy  

i2cSendByte(i2cREG1, 0x00); // 2nd byte dummy  

I2CMDR_bit.STP = 1;   // stop send

 

(2) Below code can read data from PCF8575. However, PCF8575 read input mode needs to write '1' to the I/O pins before reading.

When I use below read code following above write code, It receiving does not work, it stuck at checking "RXRDY" while loop in i2cReceiveByte().

I tried to insert I2C reset between write and read codes, which helps to read ony the 1st byte, then stuck.

Please advice if have something wrong or this related above "two bytes delay" issue?

I2CMDR_bit.MST = 1;        // Still as Master  

I2CMDR_bit.NACKMOD = 0;    //send ACK to Slave  

I2CMDR_bit.RM = 1;         // repeat mode  

I2CMDR_bit.TRX = 0;        //set as Receiving mode  

I2CMDR_bit.STT = 1;        // Start

  i2cSendByte(i2cREG1, 0x41);    // send Slave address and R/W=1

    I2CRD1 = i2cReceiveByte(i2cREG1);   // Read 1st byte     - i2cReceiveByte() just check and write RXRDY=1, then return I2CDRR value.

    I2CRD2 = i2cReceiveByte(i2cREG1);   // Read 2nd byte

    I2CRD1 = i2cReceiveByte(i2cREG1);   // Read 1st byte

    keep reading ... until

   I2CMDR_bit.NACKMOD = 1;  // set NACK to tell Slave to finish data sending   

   I2CRD1 = i2cReceiveByte(i2cREG1);   // Read the last byte, and sent NACK to slave      

 I2CMDR_bit.STP = 1;      // stop the communication.  

 

Thanks,

Yanzhong

  • Hi Yanzhong,

          Thanks for your post. I have forwarded your post to Zhaohong. He will get back to you soon. 

    Best Regards,
    Shelford

  • Yanzhong,

    You need to use 7 bit address mode. Not the free data format mode. Are all the PFC8575 address a0, a1,a2 pins tied to ground? I saw that you use address 0x40 for writing.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    Yes, I used free data format mode (FDF ='1'). The 1st byte sent out was 7-bit Slave address (b7-b1)+ the R/W flag bit (b-0). It works just like the 7-bit address mode.

    There are 2 PCF8575 ICs on board, for their address A2A1A0, one is 000, the other is 100.  

    So I used 0x40 / 0x41 for the 1st one IC write / read;  used 0x48 / 0x49 for the other.  

     

    I just tried using 7-bit address mode (FDF='0') for write or read, the I2CSAR was used 0x20 and 0x24 for the two PCF8575 respectively.

    Write or Read was controlled by I2CMDR.TRX bit.

    Actually, it works the same way as free data format mode does.

    (1) have to write two extra dummy bytes to "push" the useful data completely sending out (like 2 write delay)

    (2) following the above write operations, the reading stuck (did not get data, no RXRDY flagged). 

    (3) if just reading operations (did not follow write), the read works. - but I only got "FF", which is not the real status of PCF8575 inputs.

     

    Thanks,

    Yanzhong

  • Zhaohong,

    I found my Master / Transmit mode cannot stop as expected.

    After send data, I set I2CMDR.STP bit to '1', which did not really stop and release the Bus. - If I keep sending data (without another START), the data still can be sent out, and PCF8575 can receive and take action. 

    The only way it can be stopped is reset (set I2CMDR.nIRS  to '0', then back to '1').  Even through, the following reading process still does not work.

    Any comments about the Master/Transmit stop?

    Thanks,

    Yanzhong

     

  • Yanzhong,

    You need to use a scope on check the signals on SDA and SCL to see what is going on. Use SCL as the trigger to the scope. Pay attention of the acknowledge signal from slave after master sending the address.  I am also attaching a I2C code example. It was used on a device with 2 I2C modules. In the example, I2C1 is the master and I2C2 is the slave. The test start with master writing to slave followed by master reading from slave.

    8535.i2c.zip

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    Here comes more facts I found ... (observed scope signals)

    Following the above mentioned writes (with 2 extra dummy bytes write), when switched to Master/Read mode,

    after Start, Master sent out the 2 dummy write bytes first, then sent out Slave address with R/W bit=1.

    Slave responsed with ACK and following 8 bit data "FF", but the Master did not generated ACK to slave.

    The Slave generated a Stop condition. The communication then stopped.

    Checked the status, NACKSNT='1' which means "A NACK was sent because the NACKMOD was set to 1" - BUT this was not true, the NACKMOD was set as '0' !!!!

     I cannot figure out why. Remember that, if No write operations in front, the Read operation itself works just fine (have ACK sent out).

    I guess it caused  by something in the Write operation.  It looks like there is 2-byte FIFO for I2CDXR ?!

    (also the status of SCD = '1', which means "a Stop condition has been sent or received").

     

    Thanks,

    Yanzhong

     

     

     

  • Yanzhong,

    Did you see the sequence on scope for the write operation?

    Start condition -> salve address + R/W bit -> data to be sent -> stop condition. 

    Check for slave acknowledgement at each step.

    You also need to set up baud rate correctly. Take a look at the example I sent earlier.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    This time, I tried using HalCOGEN tool generated codes. The results were same.

    I did not see the stop condition at above Transmit signal trail.

    Below is the 8 line codes I used, explain the test following the code.

    line1: i2cSetSlaveAdd(i2cREG1, 0x24);

    line2: i2cSetStart(i2cREG1);

    line3: i2cSendByte(i2cREG1, 0xF5);

    line4: i2cSendByte(i2cREG1, 0xFF);

    line5: while (i2cIsTxReady(i2cREG1)==0) { }   // wait

    line6: i2cSetStop(i2cREG1);

    line7: i2cSendByte(i2cREG1, 0xFF); // dummy-1

    line8: i2cSendByte(i2cREG1, 0xFF); // dummy-2

    line9: others

    (1) line5 was added, because I thought i2cSetStop() ran too fast to be really executed, and the RefManual mentioned STOP should be set when TXRDY is set.

    (2) when set a breakpoint at line7 and ran the code, the scope showed only two bytes send out (the slave address and 0xF0). There were total 19 clock pulses on SCL.

    the 9th and 18th had "ACK" (low) on SDA. After the "ACK" pulse (one clock cycle of "LOW" then back to high) at 18th clock, SDA stayed on High. So the 19 clock did not see a Low-to-High rising edge.

    (3) when set a breekpoint at line9 (removed the one at line7) and ran the code, the scope showed 3 bytes send out (the slave addr, 0xF0, and 0xFF). There were total 28 clock pulses on SCL. At the 27th and 28th clock period, it's same as above situation at 18th and 19th clock cycles - No rising edge for STOP was generated.

    For the Baud rate, because I choiced 7.3728MHz crystal for MCU, the VCLK clock was programmed as 59.904MHz.

    So I2C module clock is 59.904/(7+1) = 7.488MHz.   The baud rate was caluclated 7.488MHz/((22+5)+(43+5)) = 0.09984MHz. It's close to 100KHz baud rate.

     

    By the way, I will start another thread for some questions about on-chip ADC.

     

    Thanks,

    Yanzhong 

     

  • Yanzhong,

    The write code sequence should be as follows. You must wait for the transmission to comlete before writing next data. You need to check pin states on 8575 to make sure it gets the correct data.

     i2cSetSlaveAdd(i2cREG1, 0x24);

     i2cSetStart(i2cREG1);

    while (i2cIsTxReady(i2cREG1)==1) { }   // wait for transmission to complete

    i2cSendByte(i2cREG1, 0xF5);

    while (i2cIsTxReady(i2cREG1)==1) { }   // wait for transmission to complete

    i2cSendByte(i2cREG1, 0xFF);

    while (i2cIsTxReady(i2cREG1)==1) { }   // wait for transmission to complete

    i2cSetStop(i2cREG1);

    Thanks and regards,

    Zhaohong

  • Hi Zhaohong -

    Finally, I solved the problem - It's not the code issue. It's the pull-up resistor (10K) too big which caused the transmit unstable and no stop condition!

    We used 10K pull-up for I2C in other designs. But I remembered you mentioned the I2C needs strong pull-up earlier. So, just tried and made it.

    We can close this thread now. Thank you!!

    Yanzhong

  • Yanzhong Li said:

    Hi Zhaohong -

    Finally, I solved the problem - It's not the code issue. It's the pull-up resistor (10K) too big which caused the transmit unstable and no stop condition!

    We used 10K pull-up for I2C in other designs. But I remembered you mentioned the I2C needs strong pull-up earlier. So, just tried and made it.

    We can close this thread now. Thank you!!

    Yanzhong

    Hi Yanzhong,

        I encountered the same problem as you did. Now I change the Pull-up resistor from 10K to 2.2K . But the problem still exists. Is 2.2k still too big? How can I chose a proper pull-up resistor?

    Thanks,

    Regards,

    Look

  • Hi Look,

    All the emails from TI E2E were treated as spam, so delayed. I hope you've resolved your problem already.

    4.7K pull-up resistor was used on the TMS570LS3137 evaluation board. That's why I changed from 10K to 4.7K.

    I think 2.2K pull-up is more than enough. If it's still a problem, I'd suggest you have the TI experts check your code.

    Regards,

    Yanzhong

     

  • Hi Zhaohong,

    i followed this post, on a rm48hdk this is not working.

    On event (seconds of gap)  i will write a packet of 2 Bytes to a i2c Slave.
    It works in repition only when i call i2cInit();
    Config is on Halcogen03.05.02



    before:
    i2cInit();
    i2cSetSlaveAdd(i2cREG1, ltc6904adressGet(0));

    than on each call:
    i2cInit();
    i2cSetStart(i2cREG1);
    i2cSendByte(i2cREG1, ltcCfg[0]);
    i2cSendByte(i2cREG1, ltcCfg[1]);

    it works.

    But I dont want to reinit the i2c all time - seems not to be clean

    palyed around with:

    • automatic stop bit gerneration vas manualy set : no success
    • tried also your  suggested : while (i2cIsTxReady(i2cREG1)==1) { } (but the i2cSendByte fnc is already doing this job)

    on each call (like your example)

    i2cSetSlaveAdd(i2cREG1, ltc6904adressGet(0));
    i2cSetStart(i2cREG1);
    while (i2cIsTxReady(i2cREG1)==1) { }
    i2cSendByte(i2cREG1, ltcCfg[0]);
    while (i2cIsTxReady(i2cREG1)==1) { }
    i2cSendByte(i2cREG1, ltcCfg[1]);
    while (i2cIsTxReady(i2cREG1)==1) { }
    i2cSetStop(i2cREG1);                  

    is not working.

    Maybe you have a hint whats wrong or to config before getting deeper in the generated code of halcogen.

    Thanks in advance


    Regards

    Andreas