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.

TMS570LC4357: Can provide I2C communication steps for transmit and receive as master?

Part Number: TMS570LC4357

Hi ,

Please find below TI example code for I2C communication


/* USER CODE BEGIN (0) */
/* USER CODE END */

/* Include Files */

#include "HL_sys_common.h"

/* USER CODE BEGIN (1) */
#include "HL_i2c.h"
/* USER CODE END */

/* USER CODE BEGIN (2) */
#define DATA_COUNT 10

#define Master_Address 0x26
#define Slave_Address 0x8
#define Slave_Word_address 0x00
#define Receive_data_setup 0x1 // 1 Word address

uint8_t TX_Data_Master[DATA_COUNT] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19};
uint8_t RX_Data_Master[DATA_COUNT] = { 0 };

uint8_t TX_Data_Slave[10] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29};
uint8_t RX_Data_Slave[10] = { 0 };

#define PCF8570_ADDRESS 0x57 // All A0,A1,A2 are tied to 3.3V in PCF8570
uint32_t temp1, temp2;

/* USER CODE END */

void main(void)
{
/* USER CODE BEGIN (3) */

int repeat = 0; int delay =0;

/* I2C Init as per GUI
* Mode = Master - Transmitter
* baud rate = 100KHz
* Count = 10
* Bit Count = 8bit
*/
i2cInit();

// Master Transfer Functionality //

/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);

/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

/* Configure Data count */
/* Data Count + 1 ( Word Address) */
i2cSetCount(i2cREG1, DATA_COUNT + 1);

/* Set mode as Master */
i2cSetMode(i2cREG1, I2C_MASTER);

/* Set Stop after programmed Count */
i2cSetStop(i2cREG1);

/* Transmit Start Condition */
i2cSetStart(i2cREG1);

/* Send the Word Address */
i2cSendByte(i2cREG1, Slave_Word_address);

/* Tranmit DATA_COUNT number of data in Polling mode */
i2cSend(i2cREG1, DATA_COUNT, TX_Data_Master);

/* Wait until Bus Busy is cleared */
while(i2cIsBusBusy(i2cREG1) == true);

/* Wait until Stop is detected */
while(i2cIsStopDetected(i2cREG1) == 0);

/* Clear the Stop condition */
i2cClearSCD(i2cREG1);

/* Simple Dealya before starting Next Block */
/* Depends on how quick the Slave gets ready */
for(delay=0;delay<100000;delay++);


// Master Receive Functionality //

/*****************************************/
/*****************************************/

/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cREG1) != true);

/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);

/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

/* Configure Data count */
/* Slave address + Word address write operation before reading */
i2cSetCount(i2cREG1, Receive_data_setup);

/* Set mode as Master */
i2cSetMode(i2cREG1, I2C_MASTER);

/* Set Stop after programmed Count */
i2cSetStop(i2cREG1);

/* Transmit Start Condition */
i2cSetStart(i2cREG1);

/* Send the Word Address */
i2cSendByte(i2cREG1, Slave_Word_address);

/* Wait until Bus Busy is cleared */
while(i2cIsBusBusy(i2cREG1) == true);

/* Wait until Stop is detected */
while(i2cIsStopDetected(i2cREG1) == 0);

/* Clear the Stop condition */
i2cClearSCD(i2cREG1);

/*****************************************/
/*****************************************/

/* wait until MST bit gets cleared, this takes
* few cycles after Bus Busy is cleared */
while(i2cIsMasterReady(i2cREG1) != true);

/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);

/* Set direction to receiver */
i2cSetDirection(i2cREG1, I2C_RECEIVER);

/* Configure Data count */
/* Note: Optional - It is done in Init, unless user want to change */
i2cSetCount(i2cREG1, DATA_COUNT);

/* Set mode as Master */
i2cSetMode(i2cREG1, I2C_MASTER);

/* Set Stop after programmed Count */
i2cSetStop(i2cREG1);

/* Transmit Start Condition */
i2cSetStart(i2cREG1);

/* Tranmit DATA_COUNT number of data in Polling mode */
i2cReceive(i2cREG1, DATA_COUNT, RX_Data_Master);

/* Wait until Bus Busy is cleared */
while(i2cIsBusBusy(i2cREG1) == true);

/* Wait until Stop is detected */
while(i2cIsStopDetected(i2cREG1) == 0);

/* Clear the Stop condition */
i2cClearSCD(i2cREG1);

asm(" nop");
asm(" nop");
asm(" nop");

while(1);

/* USER CODE END */
}

/* USER CODE BEGIN (4) */
/* USER CODE END */

--------------------------------------------------------------------------------

In this code , 

Question 1:

/* Transmit Start Condition */
i2cSetStart(i2cREG1); 

Is above API i2cSetStart sending start condition?

Question 2:

/* Configure address of Slave to talk to */
i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);

is API i2cSetSlaveAdd just configuring slave address or configuring and transmitting slave address?

Question 3:

/* Set direction to Transmitter */
/* Note: Optional - It is done in Init */
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

Is i2cSetDirection API  just configuring Read/Write bit or transmitting Read/Write bit?

Question 4:

As per I2C protocol , Communication sequence is

1) start condition

2) send slave address

3) send R/W control bit

4) Data bytes

.right?

how above code is following this communication sequence? 

I need to write and read date and time from RTC chip with below sequence 

Write mode :

1) Master sends out the “Start Condition”
2) Master sends out the “Slave Address”, ACh for the RV-3129-C3; the R/W bit = “0” for write mode
3) Acknowledgement from the RV-3129-C3
4) Master sends out the “Page & Word Address” to the RV-3129-C3
5) Acknowledgement from the RV-3129-C3
6) Master sends out the “Data” to write to the address specified in step 4)
7) Acknowledgement from the RV-3129-C3
8) Steps 6) and 7) can be repeated if necessary. Within the same Memory Page, the RV-3129-C3 will
increment the word address automatically
9) Master sends out the “Stop Condition”

Read mode :

1) Master sends out the “Start condition”
2) Master sends out the “Slave Address”, ACh for the RV-3129-C3; the R/W bit = “0” for write mode
3) Acknowledgement from the RV-3129-C3
4) Master sends out the “Page & Word Address” to the RV-3129-C3
5) Acknowledgement from the RV-3129-C3
6) Master sends out the “Stop Condition”
7) Master sends out the “Start Condition”
8) Master sends out the “Slave Address”, ADh for the RV-3129-C3; the R/W bit =”1” for read mode
9) Acknowledgement from the RV-3129-C3:
At this point, the Master becomes a Receiver, the Slave becomes the Transmitter
10) The RV-3129-C3 sends out the “Data” from the “Page & Word Address” specified in step 4)
11) Acknowledgement from the Master:
At this time, the “Page & Word” Address will be automatically incremented by 1
12) Steps 10) and 11) can be repeated if necessary. Within the same Page Address, the Word Address will
be incremented automatically
13) The Master, addressed as Receiver, can stop data transmission by not generating an acknowledge on
the last byte that has been sent from the Slave Transmitter. In this event, the Slave-Transmitter must
leave the data line HIGH to enable the Master to generate a “Stop condition”
14) Master sends out the “Stop Condition”

Do you have sample code for MS570LC4357 interfacing with RTC RV-3129-C3 for setting date and time and reading them back?

  • Question 1:

    /* Transmit Start Condition */
    i2cSetStart(i2cREG1); 

    Is above API i2cSetStart sending start condition?

    It transmits start condition, salve address and read/write bit.

    Question 2:

    /* Configure address of Slave to talk to */
    i2cSetSlaveAdd(i2cREG1, PCF8570_ADDRESS);

    is API i2cSetSlaveAdd just configuring slave address or configuring and transmitting slave address?

    It set the slave address only, doesn't transmit the address to I2C bus.

    Question 3:

    /* Set direction to Transmitter */
    /* Note: Optional - It is done in Init */
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);

    Is i2cSetDirection API  just configuring Read/Write bit or transmitting Read/Write bit?

    It only configure the R/W bit, doesn't transmit the R or T bit.

    Question 4:

    As per I2C protocol , Communication sequence is

    1) start condition

    2) send slave address

    3) send R/W control bit

    4) Data bytes

    .right?

    how above code is following this communication sequence? 

    For most application, it is correct. 

    i2cSetStart(i2cREG1); will send #1, #2, and #3

    For some application, between #3 and #4, you have to send register address and R/W bit

  • Hi QJ WANG,

    Thanks for clarifying about doubts.

    I used below code

    /* Read from a slave device */
    int I2C_Read_M(short Slave_Add, short Read_Add, short Count, uint8 *buff)
    {
    int i, error, dummy;
    error = 0;

    if((i2cREG1->STR & I2C_BUSBUSY ) == 0) //test if Busy is busy
    {
    /* Clear Stop bit */
    i2cREG1->MDR &= ~(I2C_STOP_COND);
    /* Clear Start bit */
    i2cREG1->MDR &= ~(I2C_START_COND);
    /* Clear Repeat mode bit */
    i2cREG1->MDR &= ~(I2C_REPEATMODE);

    /* Set direction to Transmitter */
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
    /* Set mode as Master */
    i2cSetMode(i2cREG1, I2C_MASTER);
    /* Configure Data count */
    i2cSetCount(i2cREG1, 0x01); //for 1-byte read address

    /* Configure address of Slave to talk to */
    i2cSetSlaveAdd(i2cREG1, Slave_Add);

    /* send the read address */
    i2cSendByte(i2cREG1, Read_Add);

    /* Start transmit*/
    i2cSetStart(i2cREG1); // Start the transmission:
    //I2C Bus: Start--Slave Addr--Read Addr

    while( ((i2cREG1->STR & I2C_NACK) == 0) && ((i2cREG1->STR & I2C_ARDY) == 0) );

    if((i2cREG1->STR & I2C_NACK) == 0) // Check for Positive Acknoledge
    { // Application can continue
    /* Set mode as Master, and Receiver */
    i2cSetMode(i2cREG1, I2C_MASTER); // Switch to Master Receiver
    i2cSetDirection(i2cREG1, I2C_RECEIVER);
    /* Set Repeat start mode */
    i2cREG1->MDR |= I2C_REPEATMODE;

    /* Start transmit*/
    i2cSetStart(i2cREG1); //I2C BUS: Start--Slave Addr

    for (i=0; i<Count; i++)
    {
    buff[i] = i2cReceiveByte(i2cREG1); // Read incoming data and store in array
    if (i == Count-2){
    i2cSetStop(i2cREG1); //to generate a STOP
    }
    }
    }
    else
    {
    dummy = i2cREG1->IVR; // Clear nack flag
    i2cSetStop(i2cREG1); // to generate a STOP
    error=-2; // Set error as NoAck
    }
    }
    else{
    error = -1; // Set error as Bus Busy
    }

    while((i2cREG1->MDR & I2C_STOP_COND) ==1);

    return error;
    }


    /* Write to a slave device */
    int I2C_Write_M(short Slave_Add, short Write_Add, short Count, uint8 *buff )
    {
    int error, dummy; // Return code
    error = 0x00; // Default, no error

    if((i2cREG1->STR & I2C_BUSBUSY ) == 0) //test if Busy is busy
    {
    /* Set direction to Transmitter */
    i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
    /* Set mode as Master */
    i2cSetMode(i2cREG1, I2C_MASTER);

    /* Clear Start bit */
    i2cREG1->MDR &= ~(I2C_START_COND);
    /* Set Stop after programmed Count */
    i2cSetStop(i2cREG1);

    /* Clear RM bit */
    i2cREG1->MDR &= ~(I2C_REPEATMODE); // Not in Repeat Mode

    /* Configure Data count */
    i2cSetCount(i2cREG1, Count+1);

    /* Configure address of Slave to talk to */
    i2cSetSlaveAdd(i2cREG1, Slave_Add);

    /* Transmit Start Condition */
    i2cSetStart(i2cREG1); //I2C Bus: Start--Slave Addr

    /* send the write address */
    i2cSendByte(i2cREG1, Write_Add); // Transmit data to Select Destination Register

    if((i2cREG1->STR & I2C_NACK) == 0) // Check for Positive Acknoledge
    {
    /* Tranmit DATA_COUNT number of data in Polling mode */
    i2cSend(i2cREG1, Count, buff);
    }
    else{
    dummy = i2cREG1->IVR; // Clear nack flag
    i2cSetStop(i2cREG1); // to generate a STOP
    error=-2; // Set error as NoAck
    }
    }
    else{
    error = -1; // Set error as Bus Busy
    }

    while((i2cREG1->MDR & I2C_STOP_COND) ==1);

    return error;
    }

    /* USER CODE END */

    1) While writing, execution is stuck at below line

    /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
    while ((i2c->STR & (uint32)I2C_TX_INT) == 0U)
    {
    } /* Wait */

    (inside void i2cSend(i2cBASE_t *i2c, uint32 length, uint8 * data) function)

    During this time : i2c->STR is having  100 0000 0000 (0x00000400 hex) , 

    it means I2C_XSMT       = 0x0400U,  /* Transmit shift empty not  */

    I2C_TX_INT     = 0x0010U,  /* transmit data ready   */

    transmit data ready is not set.

    It looks like I2CDXR is not coping into
    the transmit shift register. 

    Why it is not copying I2CDXR into transmit shift register???

    value of i2c->STR is 0x00000410 when it execute till below line (i2cSendByte(i2cREG1, Write_Add);).

    after executing this line(i2cSendByte(i2cREG1, Write_Add);) i2c->STR becomes 100 0000 0000 (0x00000400 hex)

    /* send the write address */
    i2cSendByte(i2cREG1, Write_Add); // Transmit data to Select Destination Register

    2 ) while reading, execution is stuck at below line

    while( ((i2cREG1->STR & I2C_NACK) == 0) && ((i2cREG1->STR & I2C_ARDY) == 0) );

    because of this condition ((i2cREG1->STR & I2C_ARDY) == 0). 

    During this time : i2c->STR is having  100 0000 0000 (0x00000400 hex) , 

    it means I2C_XSMT       = 0x0400U,  /* Transmit shift empty not  */

      I2C_ARDY       = 0x0004U,  /* access ready              */*/

      access ready  is not set.

    1) what are possible route cases for these issues?

    2) is there any HAL Cogen configuration problem? Note : PINMUX is ok(No conflict).

    3) when i enable  interrupt method, execution is stuck at below line

    while ((i2c->STR & (uint32)I2C_RX_INT) == 0U)
    {
    } /* Wait */

    function :

    uint8 i2cReceiveByte(i2cBASE_t *i2c)
    {
    /*SAFETYMCUSW 28 D MR:NA <APPROVED> "Potentially infinite loop found - Hardware Status check for execution sequence" */
    while ((i2c->STR & (uint32)I2C_RX_INT) == 0U)
    {
    } /* Wait */
    /* USER CODE BEGIN (25) */
    /* USER CODE END */

    return ((uint8)i2c->DRR);
    }

  • Hello Manoraj,

    I2C SDA and SCL are open-drain. That is to say I2C master and slave devices can only drive these lines low or leave them open. The external pull-up resistors pull the lines up to Vccio (3.3V) if no I2C device is pulling it down. 

    Would you please check if the I2C lines are pulled up in your setup? 

  • Hi Qj Wang,

    Thanks for your clarification.

    I2C is working fine now