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.

TMS320F28027: I2C EEPROM read

Part Number: TMS320F28027

Hello,

I need to work with serial I2C EEPROM. My MCU is TMS320F28027.

I'm little bit disappointed that plenty of posts on the same topics did not help me.

I prefer version without interrupts (simplicity, linear function, better for bootloader).

The example with interrupts from Control suite uses FIFO, too. It did not work for more than 3 data bytes (FIFO depth 4 bytes) and it is repeatedly sending something on the bus.

The best code I found was this https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/171/3806.5126.I2C_5F00_Writing_5F00_Reading_5F00_EEPROM.txt refered fom

I used it with minor modifications (1 byte address, STP set in the end of function).

void I2C_Read(Uint16 Slave_address, Uint16 Start_address, Uint16 No_of_databytes, Uint16 Read_Array[])
{
	//////////////////////////
	// Read data from EEPROM//
	//////////////////////////
	   I2caRegs.I2CSAR = Slave_address; 			//Set slave address
	   I2caRegs.I2CCNT = 1; 						//Set count to 2 address bytes
	   I2caRegs.I2CDXR = Start_address;			//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 = Start_address & 0xFF; 			//Send eeprom low address
	   I2caRegs.I2CCNT = No_of_databytes;				//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
	   				//Stop when internal counter becomes 0
	   I2caRegs.I2CMDR.bit.STT = 1; //Repeated start, Reception will follow
	   int i;
	   for(i = 0; i < No_of_databytes; i++){
	   	while(I2caRegs.I2CSTR.bit.RRDY == 0){}; 	//I2CDRR not ready to read?
	   	Read_Array[i] = I2caRegs.I2CDRR;
	   }
	   I2caRegs.I2CMDR.bit.STP = 1;
}

When I read 4 bytes two time in a sequence I get two different readings. First call reads one more byte.

    I2C_Read(0x50, 0xFD, 3, Read_Array);

    I2C_Read(0x50, 0xFD, 3, Read_Array2);

So I get {0x10, 0x00, 0xEF} from the first reading and {0xA, 0a10, 0x00} from the second reading.

{0xEF, 0a10, 0x00} follows from the third reading.

So the readings are shifted.

Does anyone have a clue what could be wrong?

  • Hi Lukas,

    From your waveform it looks like the eeprom thinks it needs to send more bytes than you are telling it to and that no STOP condition is being sent (But it's kind of hard to see the waveform well enough to tell).

    I believe this is the solution to your problem, but you will have to test it to confirm...

    Setting I2caRegs.I2CMDR.bit.STP equal to 1 will cause the device to generate a STOP condition when the internal data counter of the I2C module counts down to 0.

    The internal data counter works in the following way:

    1. The value you have written to I2CCNT is copied to the internal counter
    2. The counter will be decremented by 1 for each byte transferred until it reaches 0
    3. If a STOP condition is requested in master mode the transfer is terminated with a STOP condition once the countdown is complete (internal data counter reaches 0)

    So I think you should try setting I2caRegs.I2CCNT equal to (No_of_databytes - 1) to allow the internal counter to reach zero.

    Hope this helps,
    Kevin
  • Hi Kevin,
    thank you very much for your answer.
    Unfortunately I disagree with you.
    a/ EEPROM does not think it has to send more. It just sends when SCL is running. So it is under MCU control.

    b/ Important fact is that during first run 4 data bytes instead of 3 are transferred. During the second run correct 3 bytes are transferred as expected but the data read from the buffer is shifted. I can try, but I think I2CCNT set to No_of_databytes - 1 will just transfer 1 less byte in each row.

    The eeprom is 24LC02B.

  • Hi Lukas,

    You may be right. I wouldn't be surprised if making I2CCNT equal to (No_of_databytes - 1) causes 3 bytes to transfer in the first run and 2 bytes in the second run, but I think it is good to test to see what's really going on.

    To clarify, the first set of bytes are {0x10, 0x00, 0xEF} and the second set are {0x0A, 0x10, 0x00}? If so, it would seem the extra 0x0A byte from the first read is being rolled over to the second set of bytes that are read. Do you agree with this?

    From your wave form I see that a NACK is generated after the extra byte (byte 4) of the first read. In Master-receiver mode AND Nonrepeat mode (That is RM = 0 in I2CMDR, which is the default) a NACK can be generated in the following ways:

    • If STP = 1 in I2CMDR, allow the internal data counter to count down to 0 and thus force a STOP condition
    • If STP = 0, make STP = 1 to generate a STOP condition
    • Reset the module (IRS = 0 in I2CMDR). = 1 to generate a STOP condition
    • Set the NACKMOD bit of I2CMDR before the rising edge of the last data bit you intend to receive

    The first point of this list makes me think it has something to do with the internal data counter. Something you could try is moving I2caRegs.I2CMDR.bit.STP = 1; into the for loop (Or even before), as a STOP condition won't be generated until the internal countdown is complete.

    Edit: Please refer to the TMS320x2802x, 2803x Piccolo Inter-Integrated Circuit (I2C) Module Reference Guide for more information.

    http://www.ti.com/lit/ug/sprufz9d/sprufz9d.pdf

    Hope this helps,
    Kevin

  • Hi Kevin,
    thank you.
    Unfortunately it did not help.
    In the waveform NACK is probably by count down to 0, but this seems to happen too late.
    I'll try something else.
    When I2caRegs.I2CMDR.bit.STP = 1 is used earlier, only two bytes are transferred and the second function call is hanging on while(I2caRegs.I2CSTR.bit.XRDY == 0){};.

    Lukas
  • Hi Lukas,

    I'm sorry that did not work. Yes, I find it odd that the NACK is happening 1 byte late and that no STOP condition is generated before then.

    So, only two bytes are received when I2caRegs.I2CMDR.bit.STP = 1 is set early AND No_of_databytes = 3 for the first call? Is a NACK being generated right after the 2nd byte?

    Best,
    Kevin