I2C communication between PICs

From Mech
Jump to navigationJump to search

Original Assignment

Microcontrollers commonly talk to each other using protocols such as RS-232, SPI (for "serial peripheral interface"), I2C (or I^2C, "I squared C," for inter-integrated circuit), CAN bus, or other. This project is to demonstrate bidirectional I2C communication between two PICs. A demonstration might have the value of an analog input (potentiometer) at one PIC displayed as a "light bar" on the LEDs of the other PIC board, and simultaneously vice-versa.

Overview

I2C is pronounced "I squared C" and stands for Inter-Integrated Circuit. Is is a 2 line communication method for one master device to control up to 112 slave devices. While it is possible to have multiple masters on the same I2c bus, this page will only deal with a one master configuration.

The two lines are named SCL and SDA where SCL is the CLock line and SDA is the DAta line. The PIC 4520 is designed to use pin 18 as SCL and pin 23 as SDA for hardware I2C. Note that pin 18 is one of the only pins not accessible on the prototyping board. An additional wire can be added as shown below.

An example communication diagram is shown below

File:I2C Data Transfer.svg

S - Start condition; P - Stop condition; B - One bit transferred; data changes allowed when clock low (blue)

Circuit

Below is a simple circuit diagram showing the master PIC with 2 close button switches. Note that pin 18 (RC3) is not brought out to the circuit board, but a wire can be soldered next to the PIC itself.

I2C Circuit Diagram.jpg


Here is an example of how to wire this.

I2C Wiring Image.jpg

Code

Full code with switch de-bouncing can be found here:

Media:I2C_Master.c

Media:I2C_Slave.c

Master

For the Master PIC, we first need to define the output pins and force hardware I2C communication.

  #use I2C(FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW)  //using hardware I2C, built into the PIC, make sure to include this line in any master I2C program

To communicate with a device, we use the following lines of code where 0x14 is the device name.

  i2c_start();               //begin transmission
  i2c_write(0x14);           //select address of device to communicate with
  i2c_write(data);           //send actual data
  i2c_stop();                //terminate communication

Slave

For the Slave PIC, we first need to define the output pins, define the name of the device and force hardware I2C communication. This device was randomly assigned name 0x14, but could have been just about any even hex number with a few exceptions noted below code.

  #use i2c(SLAVE, FAST, SCL=PIN_C3, SDA=PIN_C4, address=0x14, FORCE_HW)

The SSP interrupt is used for I2C communication. When the master begins to transmit data, the PIC goes into this interrupt.

  #INT_SSP                      //Interrupt for I2C activity
  void sspinterupt()
  {
     state = i2c_isr_state();   //Reading the type of transmission
  
     if(state < 0x80)           //Master is sending data
     {
        data = i2c_read();      //An array will be needed to store data if more than one byte is transferred
     }
     if(state == 0x80)          //Master is requesting data
     {
        i2c_write(data);
     } 
     output_d(data);            //Output data to port D to visualize
  }

Somewhere in the main section of the program, probably right away, the SSP interrupt will need to be enabled.

  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);

Address exceptions:

  0000 000 1 START byte - for slow micros without I2C h/w
  0000 001 X CBUS address - a different bus protocol
  0000 010 X Reserved for different bus format
  0000 011 X Reserved for future purposes
  0000 1XX X Hs-mode master code
  1111 1XX X Reserved for future purposes
  1111 0XX X 10-bit slave addressing