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.

I2C bit banging, EEPROM communication

hello there,

I am trying to achieve communication with EERPOM IC using I2C protocol.

M learning the protocol and implementing it for first time on own, 

But I am stuck here where i am not able to get where to go.

I am using bit banging to implement I2C protocol in TM4C123GXL eval board.

I am trying to achieve the following..

But when i dont get the data from EEPROM though EEPROM gives ACK when i write the address and control byte.

I have observed waveforms on CRO and its as observed in debug...ACK is received but not transmission of DATA from IC,

I am posting the code...i just wanted to confrm that is there anything wrong in my code.

I am trying to read 6 bytes of code from EEPROM, from address FA to FF.

//******************************************************************8
unsigned char I2CFlag;

#define _I2CError (I2CFlag & (char) 0x40)
#define _ClrI2CError (I2CFlag &= (unsigned char)(~0x40))
#define _SetI2CError (I2CFlag |= (unsigned char)0x40)


#define _SetSDA GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_1, GPIO_PIN_1);
#define _ClrSDA GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_1, 0x00);

#define _SetSCL GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0, GPIO_PIN_0);
#define _ClrSCL GPIOPinWrite(GPIO_PORTG_BASE, GPIO_PIN_0, 0x00);

#define _IsSDA ((GPIOPinRead(GPIO_PORTG_BASE,GPIO_PIN_1)) & GPIO_PIN_1 )

#define _SetSDAOutput() {GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_1);}
#define _SetSDAInput() {GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_1);}

#define _SetSCLOutput() {GPIOPinTypeGPIOOutput(GPIO_PORTG_BASE, GPIO_PIN_0);}
#define _SetSCLInput() {GPIOPinTypeGPIOInput(GPIO_PORTG_BASE, GPIO_PIN_0);}


void delay(unsigned int delCounter)
{
unsigned int cnt;
for(cnt = 0; cnt < delCounter; cnt++)
{
}
}
void Delay8bit(unsigned char i)
{
delay(1000*i);
}

void I2CStartRou(void)
{
Delay8bit(1);
_SetSDA;
Delay8bit(1);
_SetSCL;
Delay8bit(6);
_ClrSDA;
Delay8bit(4);
_ClrSCL;
Delay8bit(2);

}
//------------------------------------------------------------
void I2CStopRou(void)
{
Delay8bit(1);
_ClrSDA;
Delay8bit(2);
_SetSCL;
Delay8bit(2);
_SetSDA;
Delay8bit(1);


}

void I2CClockRou(void)
{
Delay8bit(3);
_SetSCL;
_ClrI2CError;
Delay8bit(6);
if(_IsSDA){ _SetI2CError;}
_ClrSCL;
Delay8bit(3);
}
void I2CNack(void)
{
Delay8bit(3);
_SetSDA;
Delay8bit(3);
I2CClockRou();
}

void I2COutByteRecAck(unsigned char EEPData)
{
unsigned char bit_cnt;
for(bit_cnt = (unsigned char)0x08;bit_cnt!=(unsigned char)0x00; bit_cnt--)
{
_ClrSDA;
if(EEPData & (char)0x80){_SetSDA;}
EEPData <<= (char)0x01;
I2CClockRou();
}
Delay8bit(2);
_SetSDAInput();
Delay8bit(2);
I2CNack();
Delay8bit(2);
_SetSDAOutput();
}

unsigned char I2CReadByte(void)
{
unsigned char bit_cnt, EEPData=0;
_SetSDAInput();
Delay8bit(2);
for(bit_cnt=8;bit_cnt != (char)0x00; bit_cnt--)
{
I2CClockRou();
EEPData <<= (char)0x01;
if(_I2CError){EEPData |= (char)0x01 ;}
}
_SetSDAOutput();
return EEPData;
}

//--------------------------------------
//I2C initialization

void I2CIoInit(void){
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
_SetSDAOutput();
_SetSCLOutput();
}


unsigned char eeptr =0xfa;
unsigned char pucMACAddrMit[8];

//To Write and read the data
void i2c_main(void){
unsigned char i;
pucMACAddrMit[6] =0x33;
for(i=0;i<6;i++){ //i2c Write loop
I2CStartRou();
I2COutByteRecAck(0xA0); //Device addr
I2COutByteRecAck(eeptr+i); //starting address of MAC
I2COutByteRecAck(pucMACAddrMit[6]+i);
pucMACAddrMit[i] = 00;
I2CStopRou();
Delay8bit(100);
}

for(i=0;i<6;i++){ //i2c Raad loop
I2CStartRou();
I2COutByteRecAck(0xA0); //Device addr
I2COutByteRecAck(i + eeptr); //starting address of MAC
I2CStartRou();
I2COutByteRecAck(0xA1);
pucMACAddrMit[i] = I2CReadByte();
I2CStopRou();
}
}

  • Hello Mayank,

    I can understand using bit-banging of GPIO for I2C Implementation. However let me correct a few concepts

    1. I2C is a Open Drain Protocol. In this case you have set the GPIO as Output Mode which is a Push Pull topology. This is bound to cause more troubles

    2. The devices have a minimum requirement for Setup and Hold. While it may work for the device in question with the delay loop you have put, it may not for other devices.

    Even if you would wish to learn I2C, I would refer you to the I2C Controller so that you get the timing and protocol nuances right. There is an example on bit banging to implement a I2C Master in the TIVAWare installation examples/peripheral/i2c

    As you would see that it is a mix of Timers for timing, GPIO for protocol and a software state machine to make it generic.

    Regards

    Amit

  • Bravo Amit - you are not (in any way) the "bad-guy" here.

    Poster's who reject the, "tried, true, simplified" and then fail - should not then cry "here" for help.  The most substantial, Peripheral Driver Library represents a most powerful, near universal, Solution Pack.

    Posters with highly specialized (yet too often, woefully inefficient) objectives/desires divert the forum from its, "normal/customary" mode of operation.

    You've properly pointed poster - and identified his "highly specialized DIY" mistake.  My/others' belief, "That's more than enough."

  • cb1_mobile ...your point made is very valid....but i was trying that tested method and when after many tries i didnt get anything...then i decided to go with bit banding method.....so that i was implementing it from ground and with clear and complete control over pins.

    And for the answer....i got the solution.

    I just had to lower the optimization level to zero.

    I cant point the exact reasons....but going into debug i just understood that it used to skip the code where it is supposed to receive the data from EEPROM.

    Thanks for reply.