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