/************************************************************************* * Title: I2C master library using hardware TWI interface * Author: Peter Fleury http://jump.to/fleury * File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 * Target: any AVR device with hardware TWI * Usage: API compatible with I2C Software Library i2cmaster.h **************************************************************************/ #include #include #include #include #include "timer.h" #include "debug.h" /* define CPU frequency in Mhz here if not defined in Makefile */ #ifndef F_CPU #define F_CPU 4000000UL #endif /* I2C clock in Hz */ #define SCL_CLOCK 400000L #define SCL_DURATION (1000000L/SCL_CLOCK)/2 volatile uint8_t i2c_force_stop = 0; #define TIMEOUT 3000 #define CHECK_FORCE_STOP() if(i2c_force_stop){i2c_force_stop=0;break;} #define CHECK_TIMEOUT_PRE() \ uint16_t start; \ uint8_t once = 1; #define CHECK_TIMEOUT_PRE2() \ once = 1; #define CHECK_TIMEOUT(retval) { \ if (once) { \ start = timer_read(); \ once = 0; \ } \ else { \ if (timer_elapsed(start) >= TIMEOUT) { \ i2c_forceStop(); \ return retval; \ } \ } \ } static void i2c_forceStop(void); /************************************************************************* Initialization of the I2C bus interface. Need to be called only once *************************************************************************/ void i2c_init(void) { /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ TWSR = 0; /* no prescaler */ TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ }/* i2c_init */ /************************************************************************* Issues a start condition and sends address and transfer direction. return 0 = device accessible, 1= failed to access device *************************************************************************/ unsigned char i2c_start(unsigned char address) { uint8_t twst; // send START condition TWCR = (1<