PIC Microcontroller Communication with I2C Bus – MikroC

PIC Microcontroller Communication with I2C Bus – MikroC

Watch the Video Tutorial

I²C (pronounced I-squared-C) created by Philips Semiconductors for use in communication of peripheral devices within a TV-set and commonly written as ‘I2C’ stands for Inter-Integrated Circuit and allows communication of data between I2C devices over two wires. I²C is sometimes called Two Wire Interface.
Figure 1 below demonstrates how many devices can be connected with this simple two wire systems using only two pins of the microcontroller.           

Figure 1: Slave devices connected to PIC with I²C bus

The devices don’t have to be identical as long as they support I²C protocol. In our illustration, the first device with address 1 is a digital temperature sensor, the second one is a real time clock and the third one is a serial LCD display and the bus could carry on even more devices. 
Communication takes place from the master (PIC) to the individual selected slave only as shown in this illustration, the master sends data to the slave address 2 only.
Both SCL and SDA lines are “open drain” drivers. This basically means that the chip can drive its output low, but it cannot drive it high. For the line to be able to go high you must provide pull-up resistors to the 5V supply. 
One resistor from the SCL line to the 5V line and another from the SDA line to the 5V line. You only need one set of pull-up resistors for the whole I²C bus, not for each device, as illustrated above.
The value of the resistors is not really critical anything from 1k8 to 47k can be used, their values depend on the length of the bus line. 
If the resistors are missing, the SCL and SDA lines will always be low nearly 0 volts and the I²C bus will not work.
Figure 2 below shows how the two pull up resistors (Rp) are connected.                

Figure 2: Pull-up resistors connected to I²C bus

I²C bus is suitable when the microcontroller and a device which the microcontroller should exchange data with, are in close proximity like preferably on the same PCB. these devices (usually smart devices) can be memories modules, temperature sensors, real-time clocks, DACs, ADCs, IO expanders etc.
Similar to serial communication in SPI mode, data transfer in I2C mode is synchronous and bidirectional. 
This time only two pins are used for data transmission, One for DATA: the SDA (Serial Data) and the other for CLOCK: the SCL (Serial Clock) pins.

This time only two pins are used for data transmission, One for DATA: the SDA (Serial Data) and the other for CLOCK: the SCL (Serial Clock) pins. 
This communication can support a maximum of 112 devices on the bus (The specification declares that 128 devices can be connected to the I2C bus, but it also defines 16 reserved addresses) connected in a simple way by using only two valuable I/O pins. 

Read also on Student Companion:

PIC Microcontroller Communication with SPI Bus – MikroC

Advantages of I²C:

  • It’s faster than asynchronous serial allowing large quantities of data to be transferred quickly but it slower than the SPI. The bus can operate at various speeds which are generally dictated by the slowest device on the bus. Common bus speeds are 100Kbs (kilobits per second) in Standard Mode, 400Kbs in fast mode and 1Mbs in High speed mode but a new revision of the specification allows for a maximum throughput of 3.4Mbps in High-speed Mode.
  • Another advantage of using I2C over SPI is the number of pins required. Connecting a single master to a single slave with an SPI bus requires four lines. Each additional slave requires one additional chip select I/O pin on the master. This can become very cumbersome in situations where lots of devices must be slaved to one master.
    I2C requires only two wires, like asynchronous serial, but those two wires can support up to 112 slave devices.
  • Also, unlike SPI, I2C can support a multi-master system, allowing more than one master to communicate with all devices on the bus (although the master devices can’t talk to each other over the bus and must take turns using the bus lines).
  • I2C supports multiple slaves up to 112 slave devices. I²C devices may have external address pins which allows you to assign a unique address to each device and therefore allow multiple of the same device to operate on a single bus.
  • I2C supports slave acknowledgment which means that you can be absolutely sure that you’re actually communicating with something. With SPI, a master can be sending data to nothing at all and have no way to find out.

Disadvantages of I²C:

  • Communication via I2C is more complex than with a USART or SPI communication. The signalling must adhere to a certain protocol for the devices on the bus to recognize it as valid I2C communications.
  • I2C draws more power than other serial communication busses due to the open-drain topology of the communication lines.
  • Since devices can set their communication speed, slower operational devices can delay the operation of faster speed devices.
  • he shared nature of the I2C bus can result in the entire bus hanging when a single device on the bus stops operating. Cycling the power to the bus can be used to restart the bus and restore proper operation.
  • I2C is designed for fairly short range i.e. on the same PCB as the Master or via a relatively short cable compared to RS-232, RS-485, or CAN-bus


Figure 3: I²C bus operation

As this is a synchronous serial  communication, a clock signal is necessary to synchronize the operation of both devices, is always generated by a master device (a microcontroller) and its frequency directly affects the baud rate. When master and slave components are synchronized by the clock, every data exchange is always initiated by the master. Once the MSSP module has been enabled, it waits for a Start condition to occur. The master device first sends the START bit (logic zero) through the SDA pin, then a 7 or 10-bit address of the selected slave device, and finally, the bit which requires data write (0) or read (1) to the device. 
At this point, if the slave address exists on the bus the slave will send an acknowledgment bit to the master. The data is than transferred on the SDA line in the direction that was specified by the master. An acknowledgment bit is sent at the end of each transfered byte by the receiving end of the transmission. The only exception is that when the master is in receive mode and the slave in transmit mode the master will not send an acknowledge bit after the very last bit received.

Lastly the communication is stopped with the master sending a stop command. The start and stop commands are simply a transition from high to low (Start) on the SDA line with SCL high or low to high (Stop) on the SDA line with SCL high. Transitions for the data bits are always performed while SCL is low. The high state is only for the start/stop commands.    

MikroC Pro for PIC I²C Bus Library Functions

Programming an I²C Bus communication is not difficult, most of the compilers provide library routines which make it easy. MikroC PRO for PIC provides I²C library which supports the master I²C mode
Below is a quick descriptions of I²C routines and functions For more information, please visit online the mikroC pro for PIC I²C library page.


  • Not all PIC Microcontrollers have an  I²C module. For those which don’t have an  I²C module or if any input/output either than the default hardware pins are required, the Software  I²C functions can be used. 
  • Some Microcontrollers have multiple I²C modules. In order to use the desired I²C library routine, simply change the number 1 in the function prototype with the appropriate module number. Example: I2C2_Init(100000);    // Initialize  I²C module 2.

These are the I²C library routines:

  • I2C1_Init
  • I2C1_Start
  • I2C1_Repeated_Start
  • I2C1_Is_Idle
  • I2C1_Rd
  • I2C1_Wr
  • I2C1_Stop

This function Initializes the I²C with desired clock.
Refer to device data sheet for correct values in respect with Fosc.
This routine should always be called before using any other functions of I²C Library.
The microcntroller has to have a hardware integrated  I²C module before you can use this function.

Note: Calculation of the I²C clock value is carried out by the compiler, as it would produce a relatively large code if performed on the library level. Therefore, compiler needs to know the value of the parameter in the compile time. That is why this parameter needs to be a constant, and not a variable.


This function determines if the I²C bus is free and issues START signal.
If there is no error, the function returns 0.
Before using this function, the I²C must be configured first using the I2C1_Init fuction.


This function issues repeated START signal.
Before using this function, the I²C must be configured first using the I2C1_Init function.

This function tests if I²C bus is free. If the bus is free, it returns 1, otherwise returns 0.
Before using this function, the I²C must be configured first using the I2C1_Init function.


Prototype: unsigned short I2C1_Rd(unsigned short ack);
This function reads one byte from the slave, and sends not acknowledge signal if parameter ack is 0, otherwise it sends acknowledge.
Before using this function, the I²C must be configured first using the I2C1_Init fuction and START signal needs to be issued as well using the I2C1_Start function.
This function returns one byte from the slave.


Prototype: unsigned short I2C1_Wr(unsigned short data_);
This function sends data byte (parameter data) via I²C bus. If there were no errors, it returns 0.
Returns Returns 0 if there were no errors. Description Sends data byte (parameter data) via I²C bus.
Before using this function, the I²C must be configured first using the I2C1_Init fuction and START signal needs to be issued as well using the I2C1_Start function.


This function issues STOP signal.
Before using this function, the I²C must be configured first using the I2C1_Init function.


Share this post

Select your currency