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

# i2c.c

    00001 /*! \file i2c.c \brief I2C Interface Driver for Atmel AT91. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'i2c.c'
    00005 // Title        : I2C Interface Driver for Atmel AT91
    00006 // Author       : Pascal Stang - Copyright (C) 2005-2006
    00007 // Created      : 12/10/2005
    00008 // Revised      : 10/22/2006
    00009 // Version      : 0.1
    00010 // Target MCU   : Atmel AT91 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 // system includes
    00019 #include "at91sam7s64.h"
    00020 #include "global.h"
    00021
    00022 // local includes
    00023 #include "rprintf.h"
    00024 #include "timer.h"
    00025 #include "i2c.h"
    00026
    00027 // functions
    00028 void i2cInit(void)
    00029 {
    00030     // set I/O pins for I2C
    00031     *AT91C_PIOA_PDR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
    00032     *AT91C_PIOA_ASR = AT91C_PA3_TWD | AT91C_PA4_TWCK;
    00033     // and set for open-drain
    00034     *AT91C_PIOA_MDER = AT91C_PA3_TWD | AT91C_PA4_TWCK;
    00035
    00036     // turn on clock into I2C system
    00037     AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_TWI);
    00038
    00039     // disable interrupt handling
    00040     //*AT91C_AIC_IDCR = 0xFFFFFFFF;
    00041
    00042     // set bitrate
    00043     AT91C_BASE_TWI->TWI_CWGR = 0x0001C0C0;
    00044     //AT91C_BASE_TWI->TWI_CWGR = 0x0000C0C0;
    00045
    00046     // initialize interface
    00047     AT91C_BASE_TWI->TWI_CR = AT91C_TWI_MSEN;
    00048 }
    00049
    00050 int i2cMasterSend(u08 deviceAddr, u08 length, u08 *data)
    00051 {
    00052     int status;
    00053
    00054     // prepare write transmission
    00055     AT91C_BASE_TWI->TWI_MMR = deviceAddr<<16;
    00056     // set slave device internal address
    00057     //AT91C_BASE_TWI->TWI_IADR = 0x10;
    00058     if(length)
    00059     {
    00060         // load transmit holding register
    00061         AT91C_BASE_TWI->TWI_THR = *data++;
    00062         length--;
    00063     }
    00064     // send start condition
    00065     AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;
    00066     // wait for complete (or no device)
    00067     do
    00068     {
    00069         // required in order for NACK (dev not present) to be detected and work
    00070         delay_us(50);
    00071         // check status
    00072         status = AT91C_BASE_TWI->TWI_SR;
    00073         // watch for address NACK
    00074         if(status & AT91C_TWI_NACK)
    00075             return I2C_ERROR_NODEV;
    00076     } while(!(status & AT91C_TWI_TXRDY));
    00077     // send more data
    00078     while(length)
    00079     {
    00080         // load transmit holding register
    00081         AT91C_BASE_TWI->TWI_THR = *data++;
    00082         length--;
    00083         // wait for complete
    00084         while(!(AT91C_BASE_TWI->TWI_SR & AT91C_TWI_TXRDY));
    00085     }
    00086     // send stop condition
    00087     AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;
    00088     // wait for trasmission complete
    00089     while(!(AT91C_BASE_TWI->TWI_SR & AT91C_TWI_TXCOMP));
    00090     // return ACK/NACK status
    00091     return (AT91C_BASE_TWI->TWI_SR & AT91C_TWI_NACK);
    00092 }
    00093
    00094 int i2cMasterReceive(u08 deviceAddr, u08 length, u08 *data)
    00095 {
    00096     int status;
    00097
    00098     // prepare read transmission
    00099     AT91C_BASE_TWI->TWI_MMR = (deviceAddr<<16) | AT91C_TWI_MREAD;
    00100     // dummy read the receive holding register
    00101     AT91C_BASE_TWI->TWI_RHR;
    00102     // set slave device internal address
    00103     //AT91C_BASE_TWI->TWI_IADR = 0x10;
    00104     // send start condition
    00105     AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;
    00106     // wait for complete (or no device)
    00107     do
    00108     {
    00109         // required in order for NACK (dev not present) to be detected and work
    00110         delay_us(50);
    00111         // check status
    00112         status = AT91C_BASE_TWI->TWI_SR;
    00113         // watch for address NACK
    00114         if(status & AT91C_TWI_NACK)
    00115             return I2C_ERROR_NODEV;
    00116     } while(!(status & AT91C_TWI_RXRDY));
    00117     // receive data
    00118     while(length)
    00119     {
    00120         // load transmit holding register
    00121          *data++ = AT91C_BASE_TWI->TWI_RHR;
    00122         length--;
    00123         // wait for complete
    00124         while(!(AT91C_BASE_TWI->TWI_SR & AT91C_TWI_RXRDY));
    00125     }
    00126     // send stop condition
    00127     AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;
    00128     // wait for trasmission complete
    00129     while(!(AT91C_BASE_TWI->TWI_SR & AT91C_TWI_TXCOMP));
    00130     // return ACK/NACK status
    00131     return (AT91C_BASE_TWI->TWI_SR & AT91C_TWI_NACK);
    00132 }
    00133
    00134
    00135 void i2cScanBus(void)
    00136 {
    00137     int i;
    00138     u08 packet[1];
    00139
    00140
    00141     for(i=1; i<128; i++)
    00142     {
    00143         if(!i2cMasterSend(i, 1, packet))
    00144             rprintf("I2C Device addr 0x%x -> PRESENT\n", i);
    00145         else
    00146             rprintf("I2C Device addr 0x%x -> NACK\n", i);
    00147     }
    00148 }
    00149