_i2c.c source file

7
Main Page Data Structures File List Data Fields Globals /i2c.c Go to the documentation of this file. 00001 /*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */ 00002 //***************************************************************************** 00003 // 00004 // File Name : 'i2c.c' 00005 // Title : I2C interface using AVR Two-Wire Interface (TWI) hardware 00006 // Author : Pascal Stang - Copyright (C) 2002-2003 00007 // Created : 2002.06.25 00008 // Revised : 2003.03.02 00009 // Version : 0.9 00010 // Target MCU : Atmel AVR series 00011 // Editor Tabs : 4 00012 // 00013 // Description : I2C (pronounced "eye-squared-see") is a two-wire bidirectional 00014 // network designed for easy transfer of information between a wide variety 00015 // of intelligent devices. Many of the Atmel AVR series processors have 00016 // hardware support for transmitting and receiving using an I2C-type bus. 00017 // In addition to the AVRs, there are thousands of other parts made by 00018 // manufacturers like Philips, Maxim, National, TI, etc that use I2C as 00019 // their primary means of communication and control. Common device types 00020 // are A/D & D/A converters, temp sensors, intelligent battery monitors, 00021 // MP3 decoder chips, EEPROM chips, multiplexing switches, etc. 00022 // 00023 // I2C uses only two wires (SDA and SCL) to communicate bidirectionally 00024 // between devices. I2C is a multidrop network, meaning that you can have 00025 // several devices on a single bus. Because I2C uses a 7-bit number to 00026 // identify which device it wants to talk to, you cannot have more than 00027 // 127 devices on a single bus. 00028 // 00029 // I2C ordinarily requires two 4.7K pull-up resistors to power (one each on 00030 // SDA and SCL), but for small numbers of devices (maybe 1-4), it is enough 00031 // to activate the internal pull-up resistors in the AVR processor. To do 00032 // this, set the port pins, which correspond to the I2C pins SDA/SCL, high. 00033 // For example, on the mega163, sbi(PORTC, 0); sbi(PORTC, 1);. 00034 // 00035 // For complete information about I2C, see the Philips Semiconductor 00036 // website. They created I2C and have the largest family of devices that 00037 // work with I2C. 00038 // 00039 // Note: Many manufacturers market I2C bus devices under a different or generic 00040 // bus name like "Two-Wire Interface". This is because Philips still holds 00041 // "I2C" as a trademark. For example, SMBus and SMBus devices are hardware 00042 // compatible and closely related to I2C. They can be directly connected 00043 // to an I2C bus along with other I2C devices are are generally accessed in 00044 // the same way as I2C devices. SMBus is often found on modern motherboards 00045 // for temp sensing and other low-level control tasks. 00046 // 00047 // This code is distributed under the GNU Public License 00048 // which can be found at http://www.gnu.org/licenses/gpl.txt 00049 // 00050 //***************************************************************************** 00051 00052 #include <avr/io.h> 00053 #include <avr/signal.h> 00054 #include <avr/interrupt.h> 00055 #include <avr/twi.h> 00056 00057 #include "i2c.h" 00058 00059 #include "uart.h" // include uart function library 00060 #include "rprintf.h" // include printf function library 00061 00062 00063 // Standard I2C bit rates are: 00064 // 100KHz for slow speed 00065 // 400KHz for high speed 00066 00067 // I2C state and address variables 00068 static volatile eI2cStateType I2cState; 00069 static u08 I2cDeviceAddrRW; 00070 // send/transmit buffer (outgoing data) 00071 static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; 00072 static u08 I2cSendDataIndex; 00073 static u08 I2cSendDataLength; 00074 // receive buffer (incoming data) 00075 static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; 00076 static u08 I2cReceiveDataIndex; 00077 static u08 I2cReceiveDataLength; 00078 00079 // function pointer to i2c receive routine 25-04-2011 /i2c.c Source File ccrma.stanford.edu/…/i2c_8c-source.html 1/7

Upload: vj1600

Post on 26-Mar-2015

32 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: _i2c.c Source File

Main Page Data Structures File List Data Fields Globals

/i2c.cGo to the documentation of this file.

00001 /*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */00002 //*****************************************************************************00003 //00004 // File Name : 'i2c.c'00005 // Title : I2C interface using AVR Two-Wire Interface (TWI) hardware00006 // Author : Pascal Stang - Copyright (C) 2002-200300007 // Created : 2002.06.2500008 // Revised : 2003.03.0200009 // Version : 0.900010 // Target MCU : Atmel AVR series00011 // Editor Tabs : 400012 //00013 // Description : I2C (pronounced "eye-squared-see") is a two-wire bidirectional00014 // network designed for easy transfer of information between a wide variety00015 // of intelligent devices. Many of the Atmel AVR series processors have00016 // hardware support for transmitting and receiving using an I2C-type bus.00017 // In addition to the AVRs, there are thousands of other parts made by00018 // manufacturers like Philips, Maxim, National, TI, etc that use I2C as00019 // their primary means of communication and control. Common device types00020 // are A/D & D/A converters, temp sensors, intelligent battery monitors,00021 // MP3 decoder chips, EEPROM chips, multiplexing switches, etc.00022 //00023 // I2C uses only two wires (SDA and SCL) to communicate bidirectionally00024 // between devices. I2C is a multidrop network, meaning that you can have00025 // several devices on a single bus. Because I2C uses a 7-bit number to00026 // identify which device it wants to talk to, you cannot have more than00027 // 127 devices on a single bus.00028 //00029 // I2C ordinarily requires two 4.7K pull-up resistors to power (one each on00030 // SDA and SCL), but for small numbers of devices (maybe 1-4), it is enough00031 // to activate the internal pull-up resistors in the AVR processor. To do00032 // this, set the port pins, which correspond to the I2C pins SDA/SCL, high.00033 // For example, on the mega163, sbi(PORTC, 0); sbi(PORTC, 1);.00034 //00035 // For complete information about I2C, see the Philips Semiconductor00036 // website. They created I2C and have the largest family of devices that00037 // work with I2C.00038 //00039 // Note: Many manufacturers market I2C bus devices under a different or generic00040 // bus name like "Two-Wire Interface". This is because Philips still holds00041 // "I2C" as a trademark. For example, SMBus and SMBus devices are hardware00042 // compatible and closely related to I2C. They can be directly connected00043 // to an I2C bus along with other I2C devices are are generally accessed in00044 // the same way as I2C devices. SMBus is often found on modern motherboards00045 // for temp sensing and other low-level control tasks.00046 //00047 // This code is distributed under the GNU Public License00048 // which can be found at http://www.gnu.org/licenses/gpl.txt00049 //00050 //*****************************************************************************00051 00052 #include <avr/io.h>00053 #include <avr/signal.h>00054 #include <avr/interrupt.h>00055 #include <avr/twi.h>00056 00057 #include "i2c.h"00058 00059 #include "uart.h" // include uart function library00060 #include "rprintf.h" // include printf function library00061 00062 00063 // Standard I2C bit rates are:00064 // 100KHz for slow speed00065 // 400KHz for high speed00066 00067 // I2C state and address variables00068 static volatile eI2cStateType I2cState;00069 static u08 I2cDeviceAddrRW;00070 // send/transmit buffer (outgoing data)00071 static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];00072 static u08 I2cSendDataIndex;00073 static u08 I2cSendDataLength;00074 // receive buffer (incoming data)00075 static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];00076 static u08 I2cReceiveDataIndex;00077 static u08 I2cReceiveDataLength;00078 00079 // function pointer to i2c receive routine

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 1/7

Page 2: _i2c.c Source File

00080 //! I2cSlaveReceive is called when this processor00081 // is addressed as a slave for writing00082 static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData);00083 //! I2cSlaveTransmit is called when this processor00084 // is addressed as a slave for reading00085 static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);00086 00087 // functions00088 void i2cInit(void)00089 {00090 // set pull-up resistors on I2C bus pins00091 sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc00092 sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc00093 sbi(PORTD, 0); // i2c SCL on ATmega128,6400094 sbi(PORTD, 1); // i2c SDA on ATmega128,6400095 00096 // clear SlaveReceive and SlaveTransmit handler to null00097 i2cSlaveReceive = 0;00098 i2cSlaveTransmit = 0;00099 // set i2c bit rate to 100KHz00100 i2cSetBitrate(100);00101 // enable TWI (two-wire interface)00102 sbi(TWCR, TWEN);00103 // set state00104 I2cState = I2C_IDLE;00105 // enable TWI interrupt and slave address ACK00106 sbi(TWCR, TWIE);00107 sbi(TWCR, TWEA);00108 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00109 // enable interrupts00110 sei();00111 }00112 00113 void i2cSetBitrate(u16 bitrateKHz)00114 {00115 u08 bitrate_div;00116 // set i2c bitrate00117 // SCL freq = F_CPU/(16+2*TWBR))00118 #ifdef TWPS000119 // for processors with additional bitrate division (mega128)00120 // SCL freq = F_CPU/(16+2*TWBR*4^TWPS)00121 // set TWPS to zero00122 cbi(TWSR, TWPS0);00123 cbi(TWSR, TWPS1);00124 #endif00125 // calculate bitrate division 00126 bitrate_div = ((F_CPU/1000l)/bitrateKHz);00127 if(bitrate_div >= 16)00128 bitrate_div = (bitrate_div-16)/2;00129 outb(TWBR, bitrate_div);00130 }00131 00132 void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn)00133 {00134 // set local device address (used in slave mode only)00135 outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );00136 }00137 00138 void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData))00139 {00140 i2cSlaveReceive = i2cSlaveRx_func;00141 }00142 00143 void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData))00144 {00145 i2cSlaveTransmit = i2cSlaveTx_func;00146 }00147 00148 inline void i2cSendStart(void)00149 {00150 // send start condition00151 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));00152 }00153 00154 inline void i2cSendStop(void)00155 {00156 // transmit stop condition00157 // leave with TWEA on for slave receiving00158 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));00159 }00160 00161 inline void i2cWaitForComplete(void)00162 {00163 // wait for i2c interface to complete operation00164 while( !(inb(TWCR) & BV(TWINT)) );00165 }00166 00167 inline void i2cSendByte(u08 data)

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 2/7

Page 3: _i2c.c Source File

00168 {00169 // save data to the TWDR00170 outb(TWDR, data);00171 // begin send00172 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00173 }00174 00175 inline void i2cReceiveByte(u08 ackFlag)00176 {00177 // begin receive over i2c00178 if( ackFlag )00179 {00180 // ackFlag = TRUE: ACK the recevied data00181 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00182 }00183 else00184 {00185 // ackFlag = FALSE: NACK the recevied data00186 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00187 }00188 }00189 00190 inline u08 i2cGetReceivedByte(void)00191 {00192 // retieve received data byte from i2c TWDR00193 return( inb(TWDR) );00194 }00195 00196 inline u08 i2cGetStatus(void)00197 {00198 // retieve current i2c status from i2c TWSR00199 return( inb(TWSR) );00200 }00201 00202 void i2cMasterSend(u08 deviceAddr, u08 length, u08* data)00203 {00204 u08 i;00205 // wait for interface to be ready00206 while(I2cState);00207 // set state00208 I2cState = I2C_MASTER_TX;00209 // save data00210 I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation00211 for(i=0; i<length; i++)00212 I2cSendData[i] = *data++;00213 I2cSendDataIndex = 0;00214 I2cSendDataLength = length;00215 // send start condition00216 i2cSendStart();00217 }00218 00219 void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data)00220 {00221 u08 i;00222 // wait for interface to be ready00223 while(I2cState);00224 // set state00225 I2cState = I2C_MASTER_RX;00226 // save data00227 I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation00228 I2cReceiveDataIndex = 0;00229 I2cReceiveDataLength = length;00230 // send start condition00231 i2cSendStart();00232 // wait for data00233 while(I2cState);00234 // return data00235 for(i=0; i<length; i++)00236 *data++ = I2cReceiveData[i];00237 }00238 00239 void i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data)00240 {00241 // disable TWI interrupt00242 cbi(TWCR, TWIE);00243 00244 // send start condition00245 i2cSendStart();00246 i2cWaitForComplete();00247 00248 // send device address with write00249 i2cSendByte( deviceAddr & 0xFE );00250 i2cWaitForComplete();00251 00252 // send data00253 while(length)00254 {00255 i2cSendByte( *data++ );

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 3/7

Page 4: _i2c.c Source File

00256 i2cWaitForComplete();00257 length--;00258 }00259 00260 // transmit stop condition00261 // leave with TWEA on for slave receiving00262 i2cSendStop();00263 while( !(inb(TWCR) & BV(TWSTO)) );00264 00265 // enable TWI interrupt00266 sbi(TWCR, TWIE);00267 }00268 00269 void i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data)00270 {00271 // disable TWI interrupt00272 cbi(TWCR, TWIE);00273 00274 // send start condition00275 i2cSendStart();00276 i2cWaitForComplete();00277 00278 // send device address with read00279 i2cSendByte( deviceAddr | 0x01 );00280 i2cWaitForComplete();00281 00282 // accept receive data and ack it00283 while(length > 1)00284 {00285 i2cReceiveByte(TRUE);00286 i2cWaitForComplete();00287 *data++ = i2cGetReceivedByte();00288 // decrement length00289 length--;00290 }00291 00292 // accept receive data and nack it (last-byte signal)00293 i2cReceiveByte(TRUE);00294 i2cWaitForComplete();00295 *data++ = i2cGetReceivedByte();00296 00297 // transmit stop condition00298 // leave with TWEA on for slave receiving00299 i2cSendStop();00300 00301 // enable TWI interrupt00302 sbi(TWCR, TWIE);00303 }00304 00305 void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata)00306 {00307 // disable TWI interrupt00308 cbi(TWCR, TWIE);00309 00310 // send start condition00311 i2cSendStart();00312 i2cWaitForComplete();00313 00314 // if there's data to be sent, do it00315 if(sendlength)00316 {00317 // send device address with write00318 i2cSendByte( deviceAddr & 0xFE );00319 i2cWaitForComplete();00320 00321 // send data00322 while(sendlength)00323 {00324 i2cSendByte( *senddata++ );00325 i2cWaitForComplete();00326 sendlength--;00327 }00328 }00329 00330 // if there's data to be received, do it00331 if(receivelength)00332 {00333 // send repeated start condition00334 i2cSendStart();00335 i2cWaitForComplete();00336 00337 // send device address with read00338 i2cSendByte( deviceAddr | 0x01 );00339 i2cWaitForComplete();00340 00341 // accept receive data and ack it00342 while(receivelength > 1)00343 {

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 4/7

Page 5: _i2c.c Source File

00344 i2cReceiveByte(TRUE);00345 i2cWaitForComplete();00346 *receivedata++ = i2cGetReceivedByte();00347 // decrement length00348 receivelength--;00349 }00350 00351 // accept receive data and nack it (last-byte signal)00352 i2cReceiveByte(TRUE);00353 i2cWaitForComplete();00354 *receivedata++ = i2cGetReceivedByte();00355 }00356 00357 // transmit stop condition00358 // leave with TWEA on for slave receiving00359 i2cSendStop();00360 while( !(inb(TWCR) & BV(TWSTO)) );00361 00362 // enable TWI interrupt00363 sbi(TWCR, TWIE);00364 }00365 00366 //! I2C (TWI) interrupt service routine00367 SIGNAL(SIG_2WIRE_SERIAL)00368 {00369 // read status bits00370 u08 status = inb(TWSR) & TWSR_STATUS_MASK;00371 00372 switch(status)00373 {00374 // Master General00375 case TW_START: // 0x08: Sent start condition00376 case TW_REP_START: // 0x10: Sent repeated start condition00377 // send device address00378 i2cSendByte(I2cDeviceAddrRW);00379 //outb(TWDR, I2cDeviceAddrRW);00380 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00381 break;00382 00383 // Master Transmitter & Receiver status codes00384 case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged00385 case TW_MT_DATA_ACK: // 0x28: Data acknowledged00386 if(I2cSendDataIndex < I2cSendDataLength)00387 {00388 // send data00389 i2cSendByte( I2cSendData[I2cSendDataIndex++] );00390 //outb(TWDR, I2cSendData[I2cSendDataIndex++]);00391 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00392 }00393 else00394 {00395 // transmit stop condition, enable SLA ACK00396 i2cSendStop();00397 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));00398 // set state00399 I2cState = I2C_IDLE;00400 }00401 break;00402 case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued00403 // store final received data byte00404 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);00405 // continue to transmit STOP condition00406 case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged00407 case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged00408 case TW_MT_DATA_NACK: // 0x30: Data not acknowledged00409 // transmit stop condition, enable SLA ACK00410 i2cSendStop();00411 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));00412 // set state00413 I2cState = I2C_IDLE;00414 break;00415 case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost00416 //case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost00417 // release bus00418 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00419 // set state00420 I2cState = I2C_IDLE;00421 // release bus and transmit start when bus is free00422 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));00423 break;00424 case TW_MR_DATA_ACK: // 0x50: Data acknowledged00425 // store received data byte00426 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);00427 // fall-through to see if more bytes will be received00428 case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged00429 if(I2cReceiveDataIndex < (I2cReceiveDataLength-1))00430 // data byte will be received, reply with ACK (more bytes in transfer)00431 i2cReceiveByte(TRUE);

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 5/7

Page 6: _i2c.c Source File

00432 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00433 else00434 // data byte will be received, reply with NACK (final byte in transfer)00435 i2cReceiveByte(FALSE);00436 //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00437 break;00438 00439 // Slave Receiver status codes00440 case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned00441 case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned00442 case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned00443 case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned00444 // we are being addressed as slave for writing (data will be received from master)00445 // set state00446 I2cState = I2C_SLAVE_RX;00447 // prepare buffer00448 I2cReceiveDataIndex = 0;00449 // receive data byte and return ACK00450 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00451 break;00452 case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned00453 case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned00454 // get previously received data byte00455 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);00456 // check receive buffer status00457 if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE)00458 {00459 // receive data byte and return ACK00460 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00461 }00462 else00463 {00464 // receive data byte and return NACK00465 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00466 }00467 break;00468 case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned00469 case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned00470 // receive data byte and return NACK00471 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00472 break;00473 case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave00474 // switch to SR mode with SLA ACK00475 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00476 // i2c receive is complete, call i2cSlaveReceive00477 if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);00478 // set state00479 I2cState = I2C_IDLE;00480 break;00481 00482 // Slave Transmitter00483 case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned00484 case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned00485 // we are being addressed as slave for reading (data must be transmitted back to master)00486 // set state00487 I2cState = I2C_SLAVE_TX;00488 // request data from application00489 if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);00490 // reset data index00491 I2cSendDataIndex = 0;00492 // fall-through to transmit first data byte00493 case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received00494 // transmit data byte00495 outb(TWDR, I2cSendData[I2cSendDataIndex++]);00496 if(I2cSendDataIndex < I2cSendDataLength)00497 // expect ACK to data byte00498 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00499 else00500 // expect NACK to data byte00501 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00502 break;00503 case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received00504 case TW_ST_LAST_DATA: // 0xC8:00505 // all done00506 // switch to open slave00507 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00508 // set state00509 I2cState = I2C_IDLE;00510 break;00511 00512 // Misc00513 case TW_NO_INFO: // 0xF8: No relevant state information00514 // do nothing00515 break;00516 case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition00517 // reset internal hardware and release bus00518 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));00519 // set state

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 6/7

Page 7: _i2c.c Source File

00520 I2cState = I2C_IDLE;00521 break;00522 }00523 //outb(PORTB, ~I2cState);00524 }00525 00526 /*00527 void i2cSendNI(u08 deviceAddr, u08 length, u08* data)00528 {00529 // disable TWI interrupt00530 cbi(TWCR, TWIE);00531 00532 // send start condition00533 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));00534 while( !(inb(TWCR) & BV(TWINT)) );00535 00536 // send device address with write00537 outb(TWDR, (deviceAddr&0xFE) );00538 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00539 while( !(inb(TWCR) & BV(TWINT)) );00540 00541 // send data00542 while(length)00543 {00544 outb(TWDR, *data++);00545 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00546 while( !(inb(TWCR) & BV(TWINT)) );00547 length--;00548 }00549 00550 // transmit stop condition00551 // leave with TWEA on for slave receiving00552 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));00553 // enable TWI interrupt00554 sbi(TWCR, TWIE);00555 }00556 00557 void i2cReceiveNI(u08 deviceAddr, u08 length, u08 *data)00558 {00559 // disable TWI interrupt00560 cbi(TWCR, TWIE);00561 00562 // send start condition00563 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));00564 while( !(inb(TWCR) & BV(TWINT)) );00565 00566 // send device address with read00567 outb(TWDR, (deviceAddr&0xFE) | 0x01);00568 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00569 while( !(inb(TWCR) & BV(TWINT)) );00570 00571 // accept receive data and ack it00572 while(length > 1)00573 {00574 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));00575 while( !(inb(TWCR) & BV(TWINT)) );00576 *data++ = inb(TWDR);00577 length--;00578 }00579 00580 // accept receive data and nack it (last-byte signal)00581 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));00582 while( !(inb(TWCR) & BV(TWINT)) );00583 *data++ = inb(TWDR);00584 00585 // transmit stop condition00586 // leave with TWEA on for slave receiving00587 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));00588 // enable TWI interrupt00589 sbi(TWCR, TWIE);00590 }00591 */

Generated on Fri Aug 1 10:42:41 2003 for Procyon AVRlib by 1.2.18

25-04-2011 /i2c.c Source File

ccrma.stanford.edu/…/i2c_8c-source.html 7/7