Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# i2csw.c

Go to the documentation of this file.

    00001 /*! \file i2csw.c \brief Software I2C interface using port pins. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'i2csw.c'
    00005 // Title        : Software 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 = inb(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 = inb(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