// This library provides the high-level functions needed to use the I2C // serial interface supported by the hardware of several AVR processors. #include #include #include #include "i2c.h" /********************* ****I2C Functions**** *********************/ // checks for ACK after TWINT indicates operation complete #define START_OK ((TWSR & 0xF8) == TW_START) #define REPEATED_START_OK ((TWSR&0xF8)==TW_REP_START) #define WRITE_ADDRESS_OK ((TWSR&0xF8) == TW_MT_SLA_ACK) #define READ_ADDRESS_OK ((TWSR&0xF8) == TW_MR_SLA_ACK) #define WRITE_DATA_OK ((TWSR&0xF8) == TW_MT_DATA_ACK) // don't check ACK bit on reading data, since we are setting it. #define READ_DATA_OK ((TWSR&0xF0) == TW_MR_DATA_ACK) static void i2cError(const char*err) { Serial.print("ERROR in i2c: TWSR=0x"); Serial.print(TWSR,HEX); Serial.print(" "); Serial.println(err); delay(10); } void i2cInit(void) { // set i2c bit rate to 100KHz i2cSetBitrate(100); // enable TWI (two-wire interface) sbi(TWCR, TWEN); // Enable TWI } void i2cSetBitrate(unsigned short bitrateKHz) { uint8_t bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(prescale*(16+2*TWBR)) uint8_t prescale; if (bitrateKHz <8) { prescale=16; cbi(TWSR, TWPS0); sbi(TWSR, TWPS1); } else if (bitrateKHz < 31) { prescale = 4; sbi(TWSR, TWPS0); cbi(TWSR, TWPS1); } else { prescale=1; cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); } // (set prescale=4) //calculate bitrate division // TWBR = (F_CPU/SCL / prescale -16)/2 // = F_CPU/(2*prescale*SCL) - 8 bitrate_div = F_CPU/(2000l*prescale*bitrateKHz); if(bitrate_div >= 8) bitrate_div -= 8; TWBR= bitrate_div; } // wait for TWINT to be set after every operation EXCEPT sending stop // return 0 if times out rather than completing boolean i2cWaitForComplete(uint16_t num_tries) { uint16_t i = 0; //time out variable // wait for i2c interface to complete operation while ((!(TWCR & (1<