00001 /************************************************************************* 00002 * Title: I2C master library using hardware TWI interface 00003 * Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury 00004 * File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $ 00005 * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 00006 * Target: any AVR device with hardware TWI 00007 * Usage: API compatible with I2C Software Library i2cmaster.h 00008 **************************************************************************/ 00009 #include <inttypes.h> 00010 #include <compat/twi.h> 00011 00012 #include "i2cmaster.h" 00013 00014 00015 /* define CPU frequency in Mhz here if not defined in Makefile */ 00016 #ifndef F_CPU 00017 #error "F_CPU not defind" 00018 #endif 00019 00020 /* I2C clock in Hz */ 00021 #define SCL_CLOCK 100000L 00022 00023 00024 /************************************************************************* 00025 Initialization of the I2C bus interface. Need to be called only once 00026 *************************************************************************/ 00027 void i2c_init(void) 00028 { 00029 /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ 00030 00031 TWSR = 0; /* no prescaler */ 00032 TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ 00033 00034 }/* i2c_init */ 00035 00036 00037 /************************************************************************* 00038 Issues a start condition and sends address and transfer direction. 00039 return 0 = device accessible, 1= failed to access device 00040 *************************************************************************/ 00041 unsigned char i2c_start(unsigned char address) 00042 { 00043 uint8_t twst; 00044 00045 // send START condition 00046 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); 00047 00048 // wait until transmission completed 00049 while(!(TWCR & (1<<TWINT))); 00050 00051 // check value of TWI Status Register. Mask prescaler bits. 00052 twst = TW_STATUS & 0xF8; 00053 if ( (twst != TW_START) && (twst != TW_REP_START)) return 1; 00054 00055 // send device address 00056 TWDR = address; 00057 TWCR = (1<<TWINT) | (1<<TWEN); 00058 00059 // wail until transmission completed and ACK/NACK has been received 00060 while(!(TWCR & (1<<TWINT))); 00061 00062 // check value of TWI Status Register. Mask prescaler bits. 00063 twst = TW_STATUS & 0xF8; 00064 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; 00065 00066 return 0; 00067 00068 }/* i2c_start */ 00069 00070 00071 /************************************************************************* 00072 Issues a start condition and sends address and transfer direction. 00073 If device is busy, use ack polling to wait until device is ready 00074 00075 Input: address and transfer direction of I2C device 00076 *************************************************************************/ 00077 void i2c_start_wait(unsigned char address) 00078 { 00079 uint8_t twst; 00080 00081 00082 while ( 1 ) 00083 { 00084 // send START condition 00085 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); 00086 00087 // wait until transmission completed 00088 while(!(TWCR & (1<<TWINT))); 00089 00090 // check value of TWI Status Register. Mask prescaler bits. 00091 twst = TW_STATUS & 0xF8; 00092 if ( (twst != TW_START) && (twst != TW_REP_START)) continue; 00093 00094 // send device address 00095 TWDR = address; 00096 TWCR = (1<<TWINT) | (1<<TWEN); 00097 00098 // wail until transmission completed 00099 while(!(TWCR & (1<<TWINT))); 00100 00101 // check value of TWI Status Register. Mask prescaler bits. 00102 twst = TW_STATUS & 0xF8; 00103 if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 00104 { 00105 /* device busy, send stop condition to terminate write operation */ 00106 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); 00107 00108 // wait until stop condition is executed and bus released 00109 while(TWCR & (1<<TWSTO)); 00110 00111 continue; 00112 } 00113 //if( twst != TW_MT_SLA_ACK) return 1; 00114 break; 00115 } 00116 00117 }/* i2c_start_wait */ 00118 00119 00120 /************************************************************************* 00121 Issues a repeated start condition and sends address and transfer direction 00122 00123 Input: address and transfer direction of I2C device 00124 00125 Return: 0 device accessible 00126 1 failed to access device 00127 *************************************************************************/ 00128 unsigned char i2c_rep_start(unsigned char address) 00129 { 00130 return i2c_start( address ); 00131 00132 }/* i2c_rep_start */ 00133 00134 00135 /************************************************************************* 00136 Terminates the data transfer and releases the I2C bus 00137 *************************************************************************/ 00138 void i2c_stop(void) 00139 { 00140 /* send stop condition */ 00141 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); 00142 00143 // wait until stop condition is executed and bus released 00144 while(TWCR & (1<<TWSTO)); 00145 00146 }/* i2c_stop */ 00147 00148 00149 /************************************************************************* 00150 Send one byte to I2C device 00151 00152 Input: byte to be transfered 00153 Return: 0 write successful 00154 1 write failed 00155 *************************************************************************/ 00156 unsigned char i2c_write( unsigned char data ) 00157 { 00158 uint8_t twst; 00159 00160 // send data to the previously addressed device 00161 TWDR = data; 00162 TWCR = (1<<TWINT) | (1<<TWEN); 00163 00164 // wait until transmission completed 00165 while(!(TWCR & (1<<TWINT))); 00166 00167 // check value of TWI Status Register. Mask prescaler bits 00168 twst = TW_STATUS & 0xF8; 00169 if( twst != TW_MT_DATA_ACK) return 1; 00170 return 0; 00171 00172 }/* i2c_write */ 00173 00174 00175 /************************************************************************* 00176 Read one byte from the I2C device, request more data from device 00177 00178 Return: byte read from I2C device 00179 *************************************************************************/ 00180 unsigned char i2c_readAck(void) 00181 { 00182 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); 00183 while(!(TWCR & (1<<TWINT))); 00184 00185 return TWDR; 00186 00187 }/* i2c_readAck */ 00188 00189 00190 /************************************************************************* 00191 Read one byte from the I2C device, read is followed by a stop condition 00192 00193 Return: byte read from I2C device 00194 *************************************************************************/ 00195 unsigned char i2c_readNak(void) 00196 { 00197 TWCR = (1<<TWINT) | (1<<TWEN); 00198 while(!(TWCR & (1<<TWINT))); 00199 00200 return TWDR; 00201 00202 }/* i2c_readNak */