Go Down

Topic: [Solved] I2C-like communication (Read 926 times) previous topic - next topic

Nick Gammon


You probably want to read up on the i2c protocol.


If you read the datasheet you'll see what he is saying. It does not show an ACK between the address and the data, and thus all bits will be shifted one to the left, like he said.

dhenry

Quote
Maybe you can make your point clearer?


You have a choice: either you think a non-i2c compliant device is being used with i2c; or the device datasheet made a mistake.

You can invest lots of time / efforts to write a i2c-like protocol to communicate with the device, if you pick the 1st choice;

Or you can try a i2c-compliant code on this device and see if it works.

I hope that's sufficiently clear.

karelvandeplassche

#12
Nov 19, 2012, 03:41 pm Last Edit: Nov 19, 2012, 03:43 pm by karelvandeplassche Reason: 1
I've tried different I2C master devices (Arduino, Aardvark) and they didn't work. I used a blog post used by the softwareI2Clib pylon pointed me to (http://codinglab.blogspot.nl/2008/10/i2c-on-avr-using-bit-banging.html) to create my own bit-banging application. For those interested, here is it:

Code: [Select]
// Port for the I2C
#define I2C_DDR DDRD
#define I2C_PIN PIND
#define I2C_PORT PORTD

// Pins to be used in the bit banging
#define I2C_CLK 0
#define I2C_DAT 1

#define I2C_DATA_HI() \
       I2C_DDR &= ~( 1 << I2C_DAT );\
       I2C_PORT |= ( 1 << I2C_DAT );
#define I2C_DATA_LO() \
       I2C_DDR |= ( 1 << I2C_DAT );\
       I2C_PORT  &=~ ( 1 << I2C_DAT );

#define I2C_CLOCK_HI() \
       I2C_DDR &= ~( 1 << I2C_CLK );\
       I2C_PORT |= ( 1 << I2C_CLK );
#define I2C_CLOCK_LO() \
       I2C_DDR |= ( 1 << I2C_CLK );\
       I2C_PORT  &=~ ( 1 << I2C_CLK );

int i = 0;
int g = 0;

void setup()
{
 I2C_Init();
 Serial.begin(9600);
}

void loop()
{
 
 while(i == 0)
 {
 I2C_Start();
 I2C_Write(0x01);
 g = I2C_Read(1);
 I2C_Read(1);
 I2C_Read(1);
 I2C_Read(1);
 I2C_Read(0);
 I2C_Stop();
 i++;
 }
 Serial.print(g);
 delay(500);
 
}

void I2C_WriteBit( unsigned char c )
{
if ( c > 0 )
{
I2C_DATA_HI();
}
else
{
I2C_DATA_LO();
}

I2C_CLOCK_HI();
delay(1);

I2C_CLOCK_LO();
delay(1);

if ( c > 0 )
{
I2C_DATA_LO();
}

delay(1);

}

unsigned char I2C_ReadBit()
{
I2C_DATA_HI();

I2C_CLOCK_HI();
delay(1);

unsigned char c = I2C_PIN;

I2C_CLOCK_LO();
delay(1);

return ( c >> I2C_DAT ) & 1;
}

// Inits bitbanging port, must be called before using the functions below
//
void I2C_Init()
{
I2C_PORT &= ~( ( 1 << I2C_DAT ) | ( 1 << I2C_CLK ) );

I2C_CLOCK_HI();
I2C_DATA_HI();

delay(1);
}

// Send a START Condition
//
void I2C_Start()
{
// set both to high at the same time
I2C_DDR &= ~( ( 1 << I2C_DAT ) | ( 1 << I2C_CLK ) );
delay(1);

I2C_DATA_LO();
delay(1);

I2C_CLOCK_LO();
delay(1);
}

// Send a STOP Condition
//
void I2C_Stop()
{
I2C_CLOCK_HI();
delay(1);

I2C_DATA_HI();
delay(1);
}

// write a byte to the I2C slave device
//
unsigned char I2C_Write( unsigned char c )
{
for ( char i=0;i<8;i++)
{
I2C_WriteBit( c & 128 );

c<<=1;
}

//return I2C_ReadBit();
return 0;
}


// read a byte from the I2C slave device
//
unsigned char I2C_Read( unsigned char ack )
{
unsigned char res = 0;

for ( char i=0;i<8;i++)
{
res <<= 1;
res |= I2C_ReadBit();
}

if ( ack > 0)
{
I2C_WriteBit( 0 );
}
else
{
I2C_WriteBit( 1 );
}

delay(1);

return res;
}


For those who want to use this on normal I2C devices, switch the commented lines in the I2C_Write function. I've tested it with an normal I2C slave and the library works for that. This code uses the internal pullups for both the SCL and SDA line. WARNING: don't use port 0 and 1 on non-Leonardo Arduinos. Those are used for serial communication.

With this code I can send the right waveforms (checked with an oscilloscope). However, I can't get a response from the device yet. I begin to suspect the device is broken.. But I suppose my programming question is solved now. Thanks for the help.

Go Up