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 

Generated on Mon Nov 6 23:36:58 2006 for Procyon ARMlib by  doxygen 1.4.2