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.

Compiler/TMS320F28069M: I2C driver without interrupt

Part Number: TMS320F28069M


Tool/software: TI C/C++ Compiler

Hi, I am wrting code for I2C interface.

The following is my code for I2C write and read

void I2C_setup(I2C_Handle i2cHandle)
{
i2cHandle->I2CSAR = 0x0050; // Slave address for EEPROM control code
i2cHandle->I2CPSC.all = 7; // Prescaler - need 7~12 MHz on module clock
i2cHandle->I2CCLKL = 20; // Note : must be non zero
i2cHandle->I2CCLKH = 10; // Note : must be non zero

i2cHandle->I2CFFTX.all = 0x6040; // Enable FIFO mode and TXFIFO
i2cHandle->I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT

i2cHandle->I2CMDR.all = 0x0020; // Take I2C out of reset
}

void I2C_Write(uint16_t sAddr, uint16_t addr, uint16_t data)
{
HAL_Obj* obj = (HAL_Obj*)halHandle;
uint16_t msbAddr;
uint16_t address;
char slave_addr;

slave_addr = (sAddr >> 1) & 0x7F;
msbAddr = (0x0300 & addr) >> 8;
address = addr & 0x00FF;
slave_addr = slave_addr | msbAddr;

obj->i2cHandle->I2CSAR = slave_addr;
obj->i2cHandle->I2CCNT = 2;
obj->i2cHandle->I2CDXR = address & 0x00FF;
obj->i2cHandle->I2CDXR = data & 0x00FF;
obj->i2cHandle->I2CMDR.all = 0x2E20;
while(!obj->i2cHandle->I2CSTR.bit.SCD)
;
obj->i2cHandle->I2CSTR.bit.SCD = 1;
}


uint16_t I2C_Read(uint16_t sAddr, uint16_t addr)
{
HAL_Obj* obj = (HAL_Obj*)halHandle;
uint16_t rdata;
uint16_t msbAddr;
uint16_t address;
char slave_addr;

slave_addr = (sAddr >> 1) & 0x7F;
msbAddr = (0x0300 & addr) >> 8;
address = addr & 0x00FF;
slave_addr = slave_addr | msbAddr;

while(obj->i2cHandle->I2CSTR.bit.BB)
;

while(obj->i2cHandle->I2CMDR.bit.STP)
;

obj->i2cHandle->I2CSAR = slave_addr;
obj->i2cHandle->I2CCNT = 1;
obj->i2cHandle->I2CDXR = address & 0x00FF;
obj->i2cHandle->I2CMDR.all = 0x2620;
while(!obj->i2cHandle->I2CSTR.bit.ARDY)
;
obj->i2cHandle->I2CCNT = 1;
obj->i2cHandle->I2CMDR.all = 0x2C20;
while(!obj->i2cHandle->I2CSTR.bit.SCD)
;
rdata = obj->i2cHandle->I2CDRR;

return (rdata & 0x00FF);
}

And the follwoing is code to for access to EEPROM.

I2C_Write(I2C_EEPROM_ADDR, 0, 0x34);
usDelay(50000);
data = I2C_Read(I2C_EEPROM_ADDR, 0);
UARTprintf("data = %d\n", data);

This code worked fine. But without delay, The code get stuck in read, waiting for SCD to be 1.

At that time I2CSTR is 0x1406. 

I need your help.

Thanks in advance.

  • Hi,

    You can try this one:

    //////////////////////////
    // Write data to EEPROM //
    //////////////////////////
    //I2C_SLAVE_ADDR = 0x50 address of the EEPROM
    //I am writing 'h','e','l','l','o' to the EEPROM and then read it back later
    //I2C_NUMBYTES = 5
    //[MemoryHighAddr:MemoryLowAddr] -Address within the eeprom where you want to read/write
    //Data[] has the word 'hello' and RxdData[] will store data read from the eeprom
       I2caRegs.I2CSAR = I2C_SLAVE_ADDR; 			//Set slave address
       I2caRegs.I2CCNT = I2C_NUMBYTES + 2; 			//Set count to 5 characters plus 2 address bytes
       I2caRegs.I2CDXR = MemoryHighAddr;			//Send eeprom high address            
       I2caRegs.I2CMDR.bit.TRX = 1; 				//Set to Transmit mode
       I2caRegs.I2CMDR.bit.MST = 1; 				//Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;				//Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 1; 				//Stop when internal counter becomes 0
       I2caRegs.I2CMDR.bit.STT = 1; 				//Send the start bit, transmission will follow
       while(I2caRegs.I2CSTR.bit.XRDY == 0){}; 		//Do nothing till data is shifted out
       I2caRegs.I2CDXR = MemoryLowAddr;  			//Send eeprom low address
       
       for(i = 0; i < I2C_NUMBYTES; i++){
       	while(I2caRegs.I2CSTR.bit.XRDY == 0){}; 	//Do nothing till data is shifted out
       	I2caRegs.I2CDXR = Data[i]; 					//Send out the message
       } 
    //////////////////////////
    // Read data from EEPROM//
    //////////////////////////
       I2caRegs.I2CSAR = I2C_SLAVE_ADDR; 			//Set slave address
       I2caRegs.I2CCNT = 2; 						//Set count to 2 address bytes
       I2caRegs.I2CDXR = MemoryHighAddr;			//Send eeprom high address            
       I2caRegs.I2CMDR.bit.TRX = 1; 				//Set to Transmit mode
       I2caRegs.I2CMDR.bit.MST = 1; 				//Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;				//Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 0; 				//Dont release the bus after Tx
       I2caRegs.I2CMDR.bit.STT = 1; 				//Send the start bit, transmission will follow
       
       while(I2caRegs.I2CSTR.bit.XRDY == 0){}; 		//Do nothing till data is shifted out
       I2caRegs.I2CDXR = MemoryLowAddr; 			//Send eeprom low address
       I2caRegs.I2CCNT = I2C_NUMBYTES;				//read 5 bytes from eeprom
       I2caRegs.I2CMDR.bit.TRX = 0; 				//Set to Recieve mode
       I2caRegs.I2CMDR.bit.MST = 1; 				//Set to Master mode
       I2caRegs.I2CMDR.bit.FREE = 1;				//Run in FREE mode
       I2caRegs.I2CMDR.bit.STP = 1; 				//Stop when internal counter becomes 0
       I2caRegs.I2CMDR.bit.STT = 1; //Repeated start, Reception will follow
       for(i = 0; i < I2C_NUMBYTES; i++){
       	while(I2caRegs.I2CSTR.bit.RRDY == 0){}; 	//I2CDRR not ready to read?
       	RxdData[i] = I2caRegs.I2CDRR;
       }

    Regards,

    Gautam

  • Hi, Gautam

    Thanks for your update.

    I think you don't use FIFO.

    Please provide setup for I2C for your write/read function.

    The following is my assumption for setup.

        i2cHandle->I2CSAR = 0x0050;             // Slave address for EEPROM control code

       i2cHandle->I2CPSC.all = 7;              // Prescaler - need 7~12 MHz on module clock
        i2cHandle->I2CCLKL = 20;                // Note : must be non zero
        i2cHandle->I2CCLKH = 10;                 // Note : must be non zero

       i2cHandle->I2CIER.all = 0x00;

      i2cHandle->I2CMDR.all = 0x0020;         // Take I2C out of reset

    Is it right?

    Thanks in advance.

  • Hi, Gautam

    I have one question.

    I am using Atmel-8880 EEPROM from Atmel.

    This EEPROM needs some time to finish write operation.

    If the internal writing operation for previous I2C write is not finished, the EEPROM doesn't send ACK after slave address received.

    Please let me know how to check whether the ACK is received from the EEPROM.

    the following is the flow chart for EEPROM.

    Thanks in advance.

  • Hello,

    When it's not ready to do that read, do you see the NACK bit in I2CSTR get set? Can you use that as an indicator that you need to try sending the address again?

    Whitney

  • dear Whitney,
    Thanks for your help.
    I checked I2CMDR and I2CSTR for each operation and I understand the operation of registers.
    The posted flow chart is acknowledge polling by master. Just check the ack form slave for next operation.
    As you know for C2000 STOP can't be issued without send any signal according to your databook.
    And I found the cause of problem.
    Thanks for all help from TI.
    Baeyoung