Main Page   Data Structures   File List   Data Fields   Globals  

/i2csw.c

Go to the documentation of this file.
00001 /*! \file i2csw.c \brief Software-driven I2C interface using port pins. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'i2csw.c'
00005 // Title        : Software-driven I2C interface using port pins
00006 // Author       : Pascal Stang
00007 // Created      : 11/22/2000
00008 // Revised      : 5/2/2002
00009 // Version      : 1.1
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 
00020 #include "i2csw.h"
00021 
00022 // Standard I2C bit rates are:
00023 // 100KHz for slow speed
00024 // 400KHz for high speed
00025 
00026 //#define QDEL  delay(5)        // i2c quarter-bit delay
00027 //#define HDEL  delay(10)       // i2c half-bit delay
00028 
00029 // i2c quarter-bit delay
00030 #define QDEL    asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
00031 // i2c half-bit delay
00032 #define HDEL    asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
00033 
00034 #define I2C_SDL_LO      cbi( SDAPORT, SDA)
00035 #define I2C_SDL_HI      sbi( SDAPORT, SDA)
00036 
00037 #define I2C_SCL_LO      cbi( SCLPORT, SCL); 
00038 #define I2C_SCL_HI      sbi( SCLPORT, SCL); 
00039 
00040 #define I2C_SCL_TOGGLE  HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
00041 #define I2C_START       I2C_SDL_LO; QDEL; I2C_SCL_LO; 
00042 #define I2C_STOP        HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;
00043 
00044 /*
00045 void i2ct(void)
00046 {
00047     HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
00048 }
00049 
00050 void i2cstart(void)
00051 {
00052     I2C_SDL_LO; QDEL; I2C_SCL_LO; 
00053 }
00054 
00055 void i2cstop(void)
00056 {
00057     HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;
00058 }
00059 
00060 
00061 #define I2C_SCL_TOGGLE  i2ct();
00062 #define I2C_START       i2cstart();
00063 #define I2C_STOP        i2cstop();  
00064 */
00065 
00066 UINT i2cPutbyte(u08 b)
00067 {
00068     int i;
00069     
00070     for (i=7;i>=0;i--)
00071     {
00072         if ( b & (1<<i) )
00073             I2C_SDL_HI;
00074         else
00075             I2C_SDL_LO;         // address bit
00076             I2C_SCL_TOGGLE;     // clock HI, delay, then LO
00077     }
00078 
00079     I2C_SDL_HI;                 // leave SDL HI
00080     // added    
00081     cbi(SDADDR, SDA);           // change direction to input on SDA line (may not be needed)
00082     HDEL;
00083     I2C_SCL_HI;                 // clock back up
00084     b = inp(SDAPIN) & (1<<SDA); // get the ACK bit
00085 
00086     HDEL;
00087     I2C_SCL_LO;                 // not really ??
00088     sbi(SDADDR, SDA);           // change direction back to output
00089     HDEL;
00090     return (b == 0);            // return ACK value
00091 }
00092 
00093 
00094 u08 i2cGetbyte(UINT last)
00095 {
00096     int i;
00097     u08 c,b = 0;
00098         
00099     I2C_SDL_HI;                 // make sure pullups are ativated
00100     cbi(SDADDR, SDA);           // change direction to input on SDA line (may not be needed)
00101 
00102     for(i=7;i>=0;i--)
00103     {
00104         HDEL;
00105         I2C_SCL_HI;             // clock HI
00106         c = inp(SDAPIN) & (1<<SDA);  
00107         b <<= 1;
00108         if(c) b |= 1;
00109         HDEL;
00110         I2C_SCL_LO;             // clock LO
00111     }
00112 
00113     sbi(SDADDR, SDA);           // change direction to output on SDA line
00114   
00115     if (last)
00116         I2C_SDL_HI;             // set NAK
00117     else
00118         I2C_SDL_LO;             // set ACK
00119 
00120     I2C_SCL_TOGGLE;             // clock pulse
00121     I2C_SDL_HI;                 // leave with SDL HI
00122     return b;                   // return received byte
00123 }
00124 
00125 
00126 //************************
00127 //* I2C public functions *
00128 //************************
00129 
00130 //! Initialize I2C communication
00131 void i2cInit(void)
00132 {
00133     sbi( SDADDR, SDA);          // set SDA as output
00134     sbi( SCLDDR, SCL);          // set SCL as output
00135     I2C_SDL_HI;                 // set I/O state and pull-ups
00136     I2C_SCL_HI;                 // set I/O state and pull-ups
00137 }
00138 
00139 //! Send a byte sequence on the I2C bus
00140 void i2cSend(u08 device, u08 subAddr, u08 length, u08 *data)
00141 {
00142     I2C_START;                  // do start transition
00143     i2cPutbyte(device);         // send DEVICE address
00144     i2cPutbyte(subAddr);        // and the subaddress
00145 
00146     // send the data
00147     while (length--)
00148         i2cPutbyte(*data++);
00149 
00150     I2C_SDL_LO;                 // clear data line and
00151     I2C_STOP;                   // send STOP transition
00152 }
00153 
00154 //! Retrieve a byte sequence on the I2C bus
00155 void i2cReceive(u08 device, u08 subAddr, u08 length, u08 *data)
00156 {
00157     int j = length;
00158     u08 *p = data;
00159 
00160     I2C_START;                  // do start transition
00161     i2cPutbyte(device);         // send DEVICE address
00162     i2cPutbyte(subAddr);        // and the subaddress
00163     HDEL;
00164     I2C_SCL_HI;                 // do a repeated START
00165     I2C_START;                  // transition
00166 
00167     i2cPutbyte(device | READ);  // resend DEVICE, with READ bit set
00168 
00169     // receive data bytes
00170     while (j--)
00171         *p++ = i2cGetbyte(j == 0);
00172 
00173     I2C_SDL_LO;                 // clear data line and
00174     I2C_STOP;                   // send STOP transition
00175 }
00176 

Generated on Fri Aug 1 10:42:41 2003 for Procyon AVRlib by doxygen1.2.18