⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c.txt

📁 基于AVR系列单片机实现i2c通信
💻 TXT
📖 第 1 页 / 共 2 页
字号:

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 // This code is distributed under the GNU Public License
00014 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00015 //
00016 //*****************************************************************************
00017 
00018 #include <avr/io.h>
00019 #include <avr/interrupt.h>
00020 
00021 #include "i2c.h"
00022 
00023 #include "rprintf.h"    // include printf function library
00024 #include "uart2.h"
00025 
00026 // Standard I2C bit rates are:
00027 // 100KHz for slow speed
00028 // 400KHz for high speed
00029 
00030 //#define I2C_DEBUG
00031 
00032 // I2C state and address variables
00033 static volatile eI2cStateType I2cState;
00034 static u08 I2cDeviceAddrRW;
00035 // send/transmit buffer (outgoing data)
00036 static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
00037 static u08 I2cSendDataIndex;
00038 static u08 I2cSendDataLength;
00039 // receive buffer (incoming data)
00040 static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
00041 static u08 I2cReceiveDataIndex;
00042 static u08 I2cReceiveDataLength;
00043 
00044 // function pointer to i2c receive routine
00045 //! I2cSlaveReceive is called when this processor
00046 // is addressed as a slave for writing
00047 static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData);
00048 //! I2cSlaveTransmit is called when this processor
00049 // is addressed as a slave for reading
00050 static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);
00051 
00052 // functions
00053 void i2cInit(void)
00054 {
00055     // set pull-up resistors on I2C bus pins
00056     // TODO: should #ifdef these
00057     sbi(PORTC, 0);  // i2c SCL on ATmega163,323,16,32,etc
00058     sbi(PORTC, 1);  // i2c SDA on ATmega163,323,16,32,etc
00059     sbi(PORTD, 0);  // i2c SCL on ATmega128,64
00060     sbi(PORTD, 1);  // i2c SDA on ATmega128,64
00061 
00062     // clear SlaveReceive and SlaveTransmit handler to null
00063     i2cSlaveReceive = 0;
00064     i2cSlaveTransmit = 0;
00065     // set i2c bit rate to 100KHz
00066     i2cSetBitrate(100);
00067     // enable TWI (two-wire interface)
00068     sbi(TWCR, TWEN);
00069     // set state
00070     I2cState = I2C_IDLE;
00071     // enable TWI interrupt and slave address ACK
00072     sbi(TWCR, TWIE);
00073     sbi(TWCR, TWEA);
00074     //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00075     // enable interrupts
00076     sei();
00077 }
00078 
00079 void i2cSetBitrate(u16 bitrateKHz)
00080 {
00081     u08 bitrate_div;
00082     // set i2c bitrate
00083     // SCL freq = F_CPU/(16+2*TWBR))
00084     #ifdef TWPS0
00085         // for processors with additional bitrate division (mega128)
00086         // SCL freq = F_CPU/(16+2*TWBR*4^TWPS)
00087         // set TWPS to zero
00088         cbi(TWSR, TWPS0);
00089         cbi(TWSR, TWPS1);
00090     #endif
00091     // calculate bitrate division   
00092     bitrate_div = ((F_CPU/1000l)/bitrateKHz);
00093     if(bitrate_div >= 16)
00094         bitrate_div = (bitrate_div-16)/2;
00095     outb(TWBR, bitrate_div);
00096 }
00097 
00098 void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn)
00099 {
00100     // set local device address (used in slave mode only)
00101     outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );
00102 }
00103 
00104 void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData))
00105 {
00106     i2cSlaveReceive = i2cSlaveRx_func;
00107 }
00108 
00109 void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData))
00110 {
00111     i2cSlaveTransmit = i2cSlaveTx_func;
00112 }
00113 
00114 inline void i2cSendStart(void)
00115 {
00116     // send start condition
00117     outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
00118 }
00119 
00120 inline void i2cSendStop(void)
00121 {
00122     // transmit stop condition
00123     // leave with TWEA on for slave receiving
00124     outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));
00125 }
00126 
00127 inline void i2cWaitForComplete(void)
00128 {
00129     // wait for i2c interface to complete operation
00130     while( !(inb(TWCR) & BV(TWINT)) );
00131 }
00132 
00133 inline void i2cSendByte(u08 data)
00134 {
00135     // save data to the TWDR
00136     outb(TWDR, data);
00137     // begin send
00138     outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00139 }
00140 
00141 inline void i2cReceiveByte(u08 ackFlag)
00142 {
00143     // begin receive over i2c
00144     if( ackFlag )
00145     {
00146         // ackFlag = TRUE: ACK the recevied data
00147         outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00148     }
00149     else
00150     {
00151         // ackFlag = FALSE: NACK the recevied data
00152         outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00153     }
00154 }
00155 
00156 inline u08 i2cGetReceivedByte(void)
00157 {
00158     // retieve received data byte from i2c TWDR
00159     return( inb(TWDR) );
00160 }
00161 
00162 inline u08 i2cGetStatus(void)
00163 {
00164     // retieve current i2c status from i2c TWSR
00165     return( inb(TWSR) );
00166 }
00167 
00168 void i2cMasterSend(u08 deviceAddr, u08 length, u08* data)
00169 {
00170     u08 i;
00171     // wait for interface to be ready
00172     while(I2cState);
00173     // set state
00174     I2cState = I2C_MASTER_TX;
00175     // save data
00176     I2cDeviceAddrRW = (deviceAddr & 0xFE);  // RW cleared: write operation
00177     for(i=0; i<length; i++)
00178         I2cSendData[i] = *data++;
00179     I2cSendDataIndex = 0;
00180     I2cSendDataLength = length;
00181     // send start condition
00182     i2cSendStart();
00183 }
00184 
00185 void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data)
00186 {
00187     u08 i;
00188     // wait for interface to be ready
00189     while(I2cState);
00190     // set state
00191     I2cState = I2C_MASTER_RX;
00192     // save data
00193     I2cDeviceAddrRW = (deviceAddr|0x01);    // RW set: read operation
00194     I2cReceiveDataIndex = 0;
00195     I2cReceiveDataLength = length;
00196     // send start condition
00197     i2cSendStart();
00198     // wait for data
00199     while(I2cState);
00200     // return data
00201     for(i=0; i<length; i++)
00202         *data++ = I2cReceiveData[i];
00203 }
00204 
00205 u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data)
00206 {
00207     u08 retval = I2C_OK;
00208 
00209     // disable TWI interrupt
00210     cbi(TWCR, TWIE);
00211 
00212     // send start condition
00213     i2cSendStart();
00214     i2cWaitForComplete();
00215 
00216     // send device address with write
00217     i2cSendByte( deviceAddr & 0xFE );
00218     i2cWaitForComplete();
00219 
00220     // check if device is present and live
00221     if( inb(TWSR) == TW_MT_SLA_ACK)
00222     {
00223         // send data
00224         while(length)
00225         {
00226             i2cSendByte( *data++ );
00227             i2cWaitForComplete();
00228             length--;
00229         }
00230     }
00231     else
00232     {
00233         // device did not ACK it's address,
00234         // data will not be transferred
00235         // return error
00236         retval = I2C_ERROR_NODEV;
00237     }
00238 
00239     // transmit stop condition
00240     // leave with TWEA on for slave receiving
00241     i2cSendStop();
00242     while( !(inb(TWCR) & BV(TWSTO)) );
00243 
00244     // enable TWI interrupt
00245     sbi(TWCR, TWIE);
00246 
00247     return retval;
00248 }
00249 
00250 u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data)
00251 {
00252     u08 retval = I2C_OK;
00253 
00254     // disable TWI interrupt
00255     cbi(TWCR, TWIE);
00256 
00257     // send start condition
00258     i2cSendStart();
00259     i2cWaitForComplete();
00260 
00261     // send device address with read
00262     i2cSendByte( deviceAddr | 0x01 );
00263     i2cWaitForComplete();
00264 
00265     // check if device is present and live
00266     if( inb(TWSR) == TW_MR_SLA_ACK)
00267     {
00268         // accept receive data and ack it
00269         while(length > 1)
00270         {
00271             i2cReceiveByte(TRUE);
00272             i2cWaitForComplete();
00273             *data++ = i2cGetReceivedByte();
00274             // decrement length
00275             length--;
00276         }
00277 
00278         // accept receive data and nack it (last-byte signal)
00279         i2cReceiveByte(FALSE);
00280         i2cWaitForComplete();
00281         *data++ = i2cGetReceivedByte();
00282     }
00283     else
00284     {
00285         // device did not ACK it's address,
00286         // data will not be transferred
00287         // return error
00288         retval = I2C_ERROR_NODEV;
00289     }
00290 
00291     // transmit stop condition
00292     // leave with TWEA on for slave receiving
00293     i2cSendStop();
00294 
00295     // enable TWI interrupt
00296     sbi(TWCR, TWIE);
00297 
00298     return retval;
00299 }
00300 /*
00301 void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata)
00302 {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -