#define I2C_OUT DDRB = DDRB | SDA | SCL #define I2C_IN DDRB = (DDRB | SCL) & ~SDA char I2CErrors; int I2C_MINTIME = 20; void I2CDelay(int i){ // software delay loop while (i--); } void I2CSendStart(void) { I2CErrors = 0; // reset error counter I2C_OUT; // switch ports to output direction PORTB = PORTB | SDA | SCL; I2CDelay(I2C_MINTIME); // all lines hi and wait PORTB = PORTB & ~SDA; I2CDelay(I2C_MINTIME); // data line low and wait PORTB = PORTB & ~SCL; // also clock line low } void I2CSendStop(void) { I2C_OUT; PORTB = PORTB & ~SDA & ~SCL; I2CDelay(I2C_MINTIME); // all lines low and wait PORTB = PORTB | SCL; I2CDelay(I2C_MINTIME); // clock hi and wait PORTB = PORTB | SDA; // also data line hi } void I2CSend0(void) { I2C_OUT; PORTB = PORTB & ~SDA & ~SCL; I2CDelay(I2C_MINTIME); //apply data=0 and wait PORTB = PORTB | SCL; I2CDelay(I2C_MINTIME); //clock hi and wait PORTB = PORTB & ~SCL; //clock low } void I2CSend1(void) { I2C_OUT; PORTB = PORTB | SDA; I2CDelay(I2C_MINTIME); //apply data hi and wait PORTB = PORTB | SCL; I2CDelay(I2C_MINTIME); //also clock hi and wait PORTB = PORTB & ~SCL; //clock low } char I2CGetBit(void) { char b; I2C_IN; I2CDelay(I2C_MINTIME); //wait settling time PORTB = PORTB | SCL; I2CDelay(I2C_MINTIME); //clock hi and wait b = (PINB & SDA) >> BIT_SDA; //get bit PORTB = PORTB & ~SCL; //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) { char i; char b = 0; for (i=0; i<8; i++){ b = b << 1; b = b | I2CGetBit(); }; I2CSend0(); //send Acknowledge I2C_IN; //back to input mode return b; } char I2CReceiveLastByte(void) { char i; char b = 0; for (i=0; i<8; i++){ b = b << 1; b = b | I2CGetBit(); }; I2CSend0(); //send Acknowledge I2C_IN; //back to input mode return b; }