#define I2C_SDA_LO DDRB = (DDRB | SDA) & ~SCL #define I2C_SCL_LO DDRB = (DDRB | SCL) & ~SDA #define I2C_ALL_LO DDRB = DDRB | SDA | SCL #define I2C_ALL_HI DDRB = DDRB & (~SDA & ~SCL) char I2CErrors; int I2C_MINTIME = 40; void I2CDelay(int i){ // software delay loop while (i--); } void I2CStretch(){ // wait until clock hi while(!(PINB & SCL)); } void I2CSendStart(void) { I2CErrors = 0; // reset error counter // switch ports to output direction I2C_ALL_HI; I2CDelay(I2C_MINTIME); I2CStretch(); // all lines hi and wait I2C_SDA_LO; I2CDelay(I2C_MINTIME); // data line low and wait I2C_ALL_LO; // also clock line low } void I2CSendStop(void) { I2C_ALL_LO; I2CDelay(I2C_MINTIME); // all lines low and wait I2C_SDA_LO; I2CDelay(I2C_MINTIME); I2CStretch();// clock hi and wait I2C_ALL_HI; // also data line hi } void I2CSend0(void) { I2C_ALL_LO; I2CDelay(I2C_MINTIME); //apply data=0 and wait I2C_SDA_LO; I2CDelay(I2C_MINTIME); I2CStretch(); //clock hi and wait I2C_ALL_LO; //clock low } void I2CSend1(void) { I2C_SCL_LO; I2CDelay(I2C_MINTIME); //apply data hi and wait I2C_ALL_HI; I2CDelay(I2C_MINTIME); I2CStretch(); //also clock hi and wait I2C_SCL_LO; //clock low } char I2CGetBit(void) //open collector { char b; I2C_SCL_LO; I2CDelay(I2C_MINTIME); //SDA Hi Z and wait I2C_ALL_HI; I2CDelay(I2C_MINTIME); I2CStretch(); //clock hi and wait b = (PINB & SDA) >> BIT_SDA; //get bit I2C_SCL_LO; //clock low return b; } void I2CSendByte(char b) { char i,p; p = 0x80; for (i=0; i<8; i++){ if ((p & b) == 0) I2CSend0(); else I2CSend1(); p = p >> 1; }; I2CErrors = I2CErrors + I2CGetBit(); //Acknowledge return; } char I2CReceiveByte(void) //open collector { char i; char b = 0; for (i=0; i<8; i++){ b = b << 1; b = b | I2CGetBit(); }; I2CSend0(); //send Acknowledge return b; } char I2CReceiveLastByte(void) //open collector { char i; char b = 0; for (i=0; i<8; i++){ b = b << 1; b = b | I2CGetBit(); }; I2CSend1(); //send Acknowledge return b; }