bitbanging I2C problem

i just can"t figure it out…

the slave simply doesnt get the bits from the port…

the slave is also bit-banged…this is purely experimental…

it hangs up…waiting for the clock…

everything else runs smoothly, the master is perfect…ie. if it doesnt

get ack, it announces that no slave was found, etc etc…

this is the putbyte fn. of the master:

int I2C_PutByte(BYTE byte)

{

BYTE n; int i=48;

SDA_Write(); // set dirn of port as output

SCL_Low(); // this is what the slave looks for

b4 beginning to read from SDA

for (n = 0x80; n!= 0; n = n>>1)

{

if ( (byte & n) == n )

SDA_High();

else

SDA_Low();

writedigit(4, (char)i);

i++;

SCL_Clock(); // scl_high(), wait, then scl_low,

wait – so slave waits for clock to become low, b4 reading next

bit

}

I2C_WaitForACK();

state = ST_IDLE;

if (ack == 1)

return I2C_OK;

else

return I2C_NACK_ON_DATA;

}

this is the getbyte fn. in the slave:

BYTE I2C_GetByte()

{

BYTE i = 0x00;

int n;

SDA_Read(); SCL_Read(); // set dirns of port as input

while(isSCL_High()); // make sure SCL is low b4

going in

for (n = 0; n < 8; n++)

{

i = i << 1;

i = i | isSDA_High();

while(isSCL_Low()); // wait for SCL to become high

– start of clock pulse

// this never comes on the lcd, but it should!! the clock

never becomes high, from the slave"s

// pov. but the master is displaying its clock on the lcd

and thats workin fine!

writedigit(4, (char)(n+48));

while(isSCL_High()); // wait for SCL to become low –

clock pulse ended – explained above

}

I2C_SendACK();

state = ST_IDLE;

return i;

}

both the fns. are called simultaneously. ie. as soon as master issues

START condn. the master begins to send the address "PutByte

(slaveaddress)" and the slave,

begins to recv the address. “GetByte (slaveaddress)”. However, the

master keeps sending the bits (its displayed on the lcd) but the slave

doesnt even receive the 1st one;

something wrong in the code above?

listed below are the isSCL_Low() and the isSCL_High() fns:

short isSCL_High()

{

SCL_Read(); BYTE incoming;

incoming = P2IN & CLKBIT;

if (incoming == CLKBIT)

return 1;

else

return 0;

//return ( ((P2IN & CLKBIT) == CLKBIT) ? 1 : 0 );

}

short isSCL_Low()

{

SCL_Read(); BYTE incoming;

incoming = P2IN & CLKBIT;

if (incoming == 0)

return 1;

else

return 0;

// return ( ((P2IN & CLKBIT) == 0x00) ? 1 : 0 ); }

}

appreciate any help i can get.

thanks,

karan[/code]

I can’t really follow your code - I need the white space indentations. Use the ‘Code’ button (it’s in between the Quote and List buttons) the next time you post code, makes it much easier to read.

With I2C routines, you have to be painfully aware of who is driving the bus. The SCL (clock) line is simple. It’s driven by the master, so all slaves should define the SCL pin as an INPUT.

The SDA line is a bit more tricky. It should be master driven until the slave needs to send a response - at which time the master must go into input mode and the slave must drive the SDA bus.

From that point you have to alternate the SDA bus back and forth depending on if you are doing a read from the device or writing to it.

I would recommend reading a microchip I2C EEPROM datasheet. Their info helped me understand how the I2C protocol worked.

Hope this helps a bit,

-Nathan

Do you have a logic analyzer? That would be the best way to find out what is going on - check it out without the slave first, to make sure it is not pulling the clock line to the incorrect state.