Sunday, April 3, 2016

I2C Communication

Designer benefits
            I2C-bus compatible ICs allow a system design to rapidly progress directly from a functional block diagram to a prototype. Moreover, since they ‘clip’ directly onto the I2C-bus without any additional external interfacing, they allow a prototype system to be modified or upgraded simply by


‘clipping’ or ‘unclipping’ ICs to or from the bus. Here are some of the features of I2C-bus compatible ICs which are particularly attractive to designers:

  • Functional blocks on the block diagram correspond with the actual ICs; designs proceed rapidly from block diagram to final schematic.
  • No need to design bus interfaces because the I2C-bus interface is already integrated on-chip.
  • Integrated addressing and data-transfer protocol allow systems to be completely software-defined
  • The same IC types can often be used in many different applications
  • Design-time reduces as designers quickly become familiar with the frequently used functional blocks represented by I2C-bus compatible ICs
  • ICs can be added to or removed from a system without affecting any other circuits on the bus
  • Fault diagnosis and debugging are simple; malfunctions can be immediately traced
  • Software development time can be reduced by assembling a library of reusable software modules.
           
            In addition to these advantages, the CMOS ICs in the I2C-bus compatible range offer designers special features which are particularly attractive for portable equipment and battery-backed systems.
They all have:
  • Extremely low current consumption
  • High noise immunity
  • Wide supply voltage range
  • Wide operating temperature range.

INTRODUCTION TO THE I2C-BUS SPECIFICATION
            For 8-bit oriented digital control applications, such as those requiring microcontrollers, certain design criteria can be established:
  • A complete system usually consists of at least one microcontroller and other peripheral devices such as memories and I/O expanders
  • The cost of connecting the various devices within the system must be minimized
  • A system that performs a control function doesn’t require high-speed data transfer
  • Overall efficiency depends on the devices chosen and the nature of the interconnecting bus structure.

            To produce a system to satisfy these criteria, a serial bus structure is needed. Although serial buses don’t have the throughput capability of parallel buses, they do require less wiring and fewer IC connecting pins. However, a bus is not merely an interconnecting wire, it embodies all the
formats and procedures for communication within the system. Devices communicating with each other on a serial bus must have some form of protocol which avoids all possibilities of confusion, data loss and blockage of information. Fast devices must be able to communicate with slow devices. The system must not be dependent on the devices connected to it, otherwise modifications or improvements would be impossible. A procedure has also to be devised to decide which device will be in control of the bus and when. And, if different devices with different clock speeds are connected to the bus, the bus clock source must be defined. All these criteria are involved in the specification of the I2C-bus.

THE I2C-BUS CONCEPT
            The I2C-bus supports any IC fabrication process (NMOS, CMOS, bipolar). Two wires, serial data (SDA) and serial clock (SCL), carry information between the devices connected to the bus.  Each device is recognized by a unique address (whether it’s a microcontroller, LCD driver, memory


or keyboard interface) and can operate as either a transmitter or receiver, depending on the function of the device. Obviously an LCD driver is only a receiver, whereas a memory can both receive and transmit data. In addition to transmitters and receivers, devices can also be considered as masters or slaves when performing data transfers (see Table 1). A master is the device which initiates a data transfer on the bus and generates the clock signals to permit that transfer. At that time, any device addressed is considered a slave.

GENERAL CHARACTERISTICS
            Both SDA and SCL are bi-directional lines, connected to a positive supply voltage via a current-source or pull-up resistor (see Fig.3). When the bus is free, both lines are HIGH. The output stages of devices connected to the bus must have an open-drain or open-collector to perform the wired-AND function. Data on the I2C-bus can be transferred at rates of up to 100 kbit/s in the Standard-mode, up to 400 kbit/s in the Fast-mode, or up to 3.4 Mbit/s in the High-speed mode. The number of interfaces connected to the bus is solely dependent on the bus capacitance limit of 400 pF. For information on High-speed mode master devices, see Section 13.

BIT TRANSFER
            Due to the variety of different technology devices (CMOS, NMOS, bipolar) which can be connected to the I2C-bus, the levels of the logical ‘0’ (LOW) and ‘1’ (HIGH) are not fixed and depend on the associated level of. One clock pulse is generated for each data bit transferred.

Data validity

            The data on the SDA line must be stable during the HIGH period of the clock. The HIGH or LOW state of the data line can only change when the clock signal on the SCL line is LOW.




START and STOP conditions
            Within the procedure of the I2C-bus, unique situations arise which are defined as START (S) and STOP (P) conditions (see Fig.5). A HIGH to LOW transition on the SDA line while SCL is
HIGH is one such unique case. This situation indicates a START condition. A LOW to HIGH transition on the SDA line while SCL is HIGH defines a STOP condition. START and STOP conditions are always generated by the master. The bus is considered to be busy after the START condition. The bus is considered to be free again a certain time after the STOP condition. This bus free situation is specified in Section 15. The bus stays busy if a repeated START (Sr) is generated instead of a STOP condition. In this respect, the START (S) and repeated START (Sr) conditions are functionally identical (see Fig. 10). For the remainder of this document, therefore, the S symbol will be used as a generic term to represent both the START and repeated START conditions, unless Sr is particularly relevant. Detection of START and STOP conditions by devices connected to the bus is easy if they incorporate the necessary interfacing hardware. However, microcontrollers with no such interface have to sample the SDA line at least twice per clock period to sense the transition.



/*#################################################################################################*/
#define SCL_1() { pinMode(SCL_PIN,0); }
#define SCL_0() { pinMode(SCL_PIN,1); }
#define SDA_1() { pinMode(SDA_PIN,0); }
#define SDA_0() { pinMode(SDA_PIN,1); }

void i2c_start(void)
{
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);
  SDA_0();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);

return;
}
/*#################################################################################################*/

void i2c_stop(void)
{
  SDA_0();
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SDA_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);

return;
}
/*#################################################################################################*/


TRANSFERRING DATA

Byte format
            Every byte put on the SDA line must be 8-bits long. The number of bytes that can be transmitted per transfer is unrestricted. Each byte has to be followed by an acknowledge bit. Data is transferred with the most significant bit (MSB) first (see Fig.6). If a slave can’t receive or transmit another complete byte of data until it has performed some other function, for example servicing an internal interrupt, it can hold the clock line SCL LOW to force the master into a wait state. Data transfer then continues when the slave is ready for another byte of data and releases clock line SCL. In some cases, it’s permitted to use a different format from the I2C-bus format (for CBUS compatible devices for example). A message which starts with such an address can be terminated by generation of a STOP condition, even during the transmission of a byte. In this case, no acknowledge is generated.





Acknowledge
            Data transfer with acknowledge is obligatory. The acknowledge-related clock pulse is generated by the master. The transmitter releases the SDA line (HIGH) during the acknowledge clock pulse.
            The receiver must pull down the SDA line during the acknowledge clock pulse so that it remains stable LOW during the HIGH period of this clock pulse (see Fig.7). Of course, set-up and hold times must also be taken into account.
            Usually, a receiver which has been addressed is obliged to generate an acknowledge after each byte has been received, except when the message starts with a CBUS address
            When a slave doesn’t acknowledge the slave address (for example, it’s unable to receive or transmit because it’s performing some real-time function), the data line must be left HIGH by the slave. The master can then generate either a STOP condition to abort the transfer, or a repeated START condition to start a new transfer.
            If a slave-receiver does acknowledge the slave address but, some time later in the transfer cannot receive any more data bytes, the master must again abort the transfer. This is indicated by the slave generating the not-acknowledge on the first byte to follow. The slave leaves the data line HIGH and the master generates a STOP or a repeated START condition.
            If a master-receiver is involved in a transfer, it must signal the end of data to the slave- transmitter by not generating an acknowledge on the last byte that was clocked out of the slave. The slave-transmitter must release the data line to allow the master to generate a STOP or repeated START condition.








I2C Interface Library for arduino:
Define your connections SCL SDA connections
//blog.circuits4you.com
//Dt. 24-3-2016
//===========================================================================
//Enter your hardware connections here
#define SDA_PIN     4         /* The SDA port pin */
#define SCL_PIN     5         /* The SCL port pin */
//===========================================================================

#define I2C_DELAY     5     //( (I2C_DELAY_TIME*(F_CPU/60000))/100 )  
#define I2C_TIMEOUT   1000  // ( (I2C_TIMEOUT_TIME*(F_CPU/60000))/100 ) 

#define I2C_READ  1
#define I2C_WRITE 0

#define I2C_QUIT  0
#define I2C_CONTINUE  1

#define I2C_NO_ERROR       0
#define I2C_ERROR_DEVICE_BUSY    1
#define I2C_ERROR_DEVICE_NOT_RESPONDING  2

/* Macro definitions */

#define I2C_START(ADDRESS)     { i2c_start(); i2c_transmit(ADDRESS); }
#define I2C_START_TX(ADDRESS)  I2C_START(ADDRESS)
#define I2C_START_RX(ADDRESS)  I2C_START(ADDRESS | I2C_READ)
//------------------------------------
#define SCL_1() { pinMode(SCL_PIN,0); }
#define SCL_0() { pinMode(SCL_PIN,1); }
#define SDA_1() { pinMode(SDA_PIN,0); }
#define SDA_0() { pinMode(SDA_PIN,1); }

#define RELEASE_I2C_BUS() { SCL_1(); SDA_1(); }


void i2c_start(void);
void i2c_init(void);
void i2c_stop(void);
unsigned char i2c_transmit(unsigned char data);
unsigned char i2c_receive(unsigned char ack);

/*#################################################################################################*/
void i2c_init(void)
{
  digitalWrite(SDA_PIN,0);
  digitalWrite(SCL_PIN,0);
  
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_TIMEOUT);
  i2c_start();
  delayMicroseconds(I2C_TIMEOUT);
  i2c_stop();
  delayMicroseconds(I2C_TIMEOUT);
return;
}
/*#################################################################################################*/

void i2c_start(void)
{
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);
  SDA_0();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);

return;
}
/*#################################################################################################*/

void i2c_stop(void)
{
  SDA_0();
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SDA_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);

return;
}
/*#################################################################################################*/

unsigned char i2c_transmit(unsigned char data)
{
register unsigned char bit=0;

  for(bit=0; bit<=7; bit++)
    {
        if( data & 0x80 ) { SDA_1(); } else { SDA_0(); }
        SCL_1();
        delayMicroseconds(I2C_DELAY);
        SCL_0();
        delayMicroseconds(I2C_DELAY);
        data = (data<<1);
    }
  /* Look for AKNOWLEDGE */
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);


  if(digitalRead(SDA_PIN)==0) //bit_is_clear(I2C_SDA_PIN_REG, SDA_PIN) )
   {
       SCL_0();
       delayMicroseconds(I2C_DELAY);
   }
  else{
     delayMicroseconds(I2C_TIMEOUT);
     if(digitalRead(SDA_PIN)==0)  //bit_is_clear(I2C_SDA_PIN_REG, SDA_PIN) )
      {
         SCL_0();
         delayMicroseconds(I2C_DELAY);
      }
     else { return(I2C_ERROR_DEVICE_NOT_RESPONDING); }
      }


  if(digitalRead(SDA_PIN)==0)   // bit_is_clear(I2C_SDA_PIN_REG, SDA_PIN) ) 
   { 
         delayMicroseconds(I2C_TIMEOUT);
         if(digitalRead(SDA_PIN)==0)  // bit_is_clear(I2C_SDA_PIN_REG, SDA_PIN) ) 
         { return(I2C_ERROR_DEVICE_BUSY); }
   }   

return(I2C_NO_ERROR);   
}
/*#################################################################################################*/

unsigned char i2c_receive(unsigned char ack)
{
register unsigned char bit=0, data=0;

  SDA_1();
  for(bit=0; bit<=7; bit++)
    {
        SCL_1();
        delayMicroseconds(I2C_DELAY);
        data = (data<<1);
        if(digitalRead(SDA_PIN)==1)  //bit_is_set(I2C_SDA_PIN_REG, SDA_PIN) ) 
        { data++; }
        SCL_0();
        delayMicroseconds(I2C_DELAY);
    }
  
  /* if CONTINUE then send AKNOWLEDGE else if QUIT do not send AKNOWLEDGE (send Nack) */       
  if(ack==I2C_CONTINUE) { SDA_0(); }  else { SDA_1(); }
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);

return data;
}
/*#################################################################################################*/


Please comment for any questions and query.


No comments:

Post a Comment