Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Lab # 4

Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

Embedded Systems Lab # 4 MTE-409

 Objective:
Introduction to I2C Protocol. Configuration of I2C registers for communication.

 Apparatus:
i. PIC 16F877A
ii. Resistor (1 kΩ)
iii. I2C Debugger

 Softwares:
i. MPLABX IDE
ii. XC8 compiler
iii. Proteus.

 Theory:
1) I2C Communication:
I²C (Inter-Integrated Circuit), is a multi-master, multi-slave, packet switched, single-ended, serial
computer bus invented in 1982 by Philips. The I2C bus is a bi-directional two-wire serial bus that provides
a communication link between integrated circuits. It is a synchronous protocol that allows a master device
to initiate communication with a slave device. Data is exchanged one bit at a time.
The two wires, or lines are called Serial Clock (or SCL) and Serial Data (or SDA). The SCL line is the
clock signal line, generated by the master which synchronize the data transfer between the devices on the
I2C bus. The other line is the SDA line which carries the data.
Both the lines are “open-drain” which means that pull up resistors needs to be attached to them so that
the lines are high because the devices on the I2C bus are active low. Commonly used values for the resistors
are from 2k for higher speeds at about 400 kbps, to 10k for lower speed at about 100 kbps. The I2C mode
fully implements all master and slave functions and provides interrupts on Start and Stop bits in hardware
to determine a free bus (multi-master function). It supports 7-bit and 10-bit addressing and can connect up
to 127 devices with only two wires. The user must configure these pins as inputs or outputs.
a) Master:
A device on the I2C bus which starts the communication.
b) Slave:
A device which is being addressed by Master.
2) Protocol:
The data signal is transferred in sequences of 8-bits. So, after a special start condition occurs comes the
first 8-bits sequence which indicates the address of the slave to which the data is being sent. The device
addressing sequence starts with the most significant bit (MSB) first and ends with the least significant bit
(LSB) and it’s actually composed of 7 bits because the 8th bit is used for indicating whether the master will
write to the slave (logic low) or read from it (logic high). After each 8-bits sequence follows a bit called
Acknowledge. After the first Acknowledge bit in most cases comes another addressing sequence but this

Attique Ur Rehman (17-003) Page # 1


Embedded Systems Lab # 4 MTE-409
time for the internal registers of the slave device. After the addressing sequences follows the data sequences
as many until the data is completely sent and it ends with a special stop condition.

I2C communication can only start if the bus is idle.


3) Register:
The MSSP module has six registers for I2C operation. These are:
i. MSSP Control Register (SSPCON)
ii. MSSP Control Register 2 (SSPCON2)
iii. MSSP Status Register (SSPSTAT)
iv. Serial Receive/Transmit Buffer Register (SSPBUF)
v. MSSP Shift Register (SSPSR) – Not directly accessible
vi. MSSP Address Register (SSPADD)
SSPCON, SSPCON2 and SSPSTAT are the control and status registers in I2C mode operation. The
SSPCON and SSPCON2 registers are readable and writable. The lower six bits of the SSPSTAT are read-
only. The upper two bits of the SSPSTAT are read/write. SSPSR is the shift register used for shifting data
in or out. SSPBUF is the buffer register to which data bytes are written to or read from. SSPADD register
holds the slave device address when the SSP is configured in I2C Slave mode.
When the SSP is configured in Master mode, the lower seven bits of SSPADD act as the baud rate
generator reload value. In receive operations, SSPSR and SSPBUF together create a double-buffered
receiver. When SSPSR receives a complete byte, it is transferred to SSPBUF and the SSPIF interrupt is set.
During transmission, the SSPBUF is not double buffered. A write to SSPBUF will write to both SSPBUF
and SSPSR.

Attique Ur Rehman (17-003) Page # 2


Embedded Systems Lab # 4 MTE-409
4) Register Configuration:

Attique Ur Rehman (17-003) Page # 3


Embedded Systems Lab # 4 MTE-409

Attique Ur Rehman (17-003) Page # 4


Embedded Systems Lab # 4 MTE-409

Attique Ur Rehman (17-003) Page # 5


Embedded Systems Lab # 4 MTE-409
5) Timing Diagram:

Attique Ur Rehman (17-003) Page # 6


Embedded Systems Lab # 4 MTE-409
6) Calculation:
Fosc = 20 MHz
Clock = 20 kHz
𝐹𝑜𝑠𝑐
Clock =
(4 ∗ (𝑆𝑆𝑃𝐴𝐷𝐷 + 1))
SSPADD = 249
7) Code:

#define _XTAL_FREQ 20000000


#include <xc.h>
__PROG_CONFIG(0,0x3F32);
/*****************************Functions Declaration****************************/
unsigned char I2C_Init(void);
unsigned char Start_I2C(void);
unsigned char Stop_I2C(void);
unsigned char Rep_Start_Cond();
unsigned char Ack_Stat();
unsigned char Ack_Event(unsigned char state);
unsigned char Trans_Byte(unsigned char data);
unsigned char Recv_Byte(void);
/******************************************************************************/
/*********************************Main Program*********************************/
void main(void)
{
//Initialize the I2C communication
I2C_Init();
//Generate the Start condition
Start_I2C();
//Send the address frame
Trans_Byte(0xD0);
//Now check for Acknowledge from the slave
if(!Ack_Stat())
{
Rep_Start_Cond();
//Wait for few milliseconds
__delay_ms(10);
//Again send the slave address
Trans_Byte(0xD0);
}

Attique Ur Rehman (17-003) Page # 7


Embedded Systems Lab # 4 MTE-409
//If Acknowledge is received then send register address
else
Trans_Byte(0xA1);
//Again check for Acknowledge
if(!Ack_Stat())
{
Rep_Start_Cond();
//Wait for few milliseconds
__delay_ms(10);
//Again send the register address
Trans_Byte(0xA1);
}
//If Acknowledge is received then send receive data from the slave
else
Recv_Byte();
//Stop the I2c Communication
Stop_I2C();
while(1);
return;
}
/******************************************************************************/
/********************************Function Definition***************************/
unsigned char I2C_Init(void)
{
//Make SDA, SCL pins as input or output. In our case, we are making them inputs.
TRISCbits.TRISC3 = 1;
TRISCbits.TRISC4 = 1;
//Configuring PIC16F877A in Master mode,
//Configuring and enabling the pins as serial port pins (SSPEN = 1)
SSPCONbits.SSPEN = 1;
//I2C master mode SSPM3 - SSPM0 = 1000.
SSPCONbits.SSPM = 8;
//Disabling the specific SMBUS inputs
SSPSTATbits.CKE = 0;
//Disabling the Slew rate speed for standard mode
SSPSTATbits.SMP = 1;
//Also find the SSPADD value by using given formula.
SSPADD = 249;
}
/******************************************************************************/

Attique Ur Rehman (17-003) Page # 8


Embedded Systems Lab # 4 MTE-409
unsigned char Start_I2C(void)
{
//Clear the Interrupt Flag
SSPIF = 0;
//Enable the Start condition by enabling the SEN bit
SSPCON2bits.SEN = 1;
//Wait till the start condition is generated . SEN will be cleared and SSPIF will be set automatically by hardware.
//i.e. SEN = 0 and SSPIF = 1.
while(SSPCON2bits.SEN == 1);
while(!SSPIF);
//Again clear the Interrupt Flag
SSPIF = 0;
}
/******************************************************************************/
unsigned char Stop_I2C()
{
//Clear the Interrupt Flag
SSPIF = 0;
//Enable the Start condition by enabling the SEN bit
SSPCON2bits.PEN = 1;
//Wait till the start condition is generated
while(SSPCON2bits.PEN);
while(!SSPIF);
//Again clear the Interrupt Flag
SSPIF = 0;
}
/******************************************************************************/
unsigned char Rep_Start_Cond()
{
//Clearing the interrupt flag
PIR1bits.SSPIF = 0;
//Enabling the Repeated Start condition by making bit RSEN = 1
SSPCON2bits.RSEN = 1;
//Waiting for bit to be cleared by hardware
while(SSPCON2bits.RSEN);
//Waiting for repeated start condition to start
while(PIR1bits.SSPIF!=1);
//Again clearing the interrupt flag
PIR1bits.SSPIF=0;
}

Attique Ur Rehman (17-003) Page # 9


Embedded Systems Lab # 4 MTE-409
/******************************************************************************/
unsigned char Ack_Stat()
{
//No Acknowledge receive if ACKSTAT = 1
if(SSPCON2bits.ACKSTAT)
return(1);
//Acknowledge received if ACKSTAT = 0
else
return(0);
}
/******************************************************************************/
//Sending Acknowledge by Master to slave.
unsigned char Ack_Event(unsigned char state)
{
if(state)
SSPCON2bits.ACKDT = 1; //User wants No ACK
else
SSPCON2bits.ACKDT = 0; //User wants ACK
//Clear Interrupt flag Before transmitting the ACK
PIR1bits.SSPIF = 0;
//Transmit the ACK Bit
SSPCON2bits.ACKEN = 1;
//Wait for completion of transmit of this but
while(SSPCON2bits.ACKEN);
//Wait for interrupt flag to become high
while(PIR1bits.SSPIF!=1);
PIR1bits.SSPIF = 0; // Clear the interrupt flag
return(state);
}
/******************************************************************************/
unsigned char Trans_Byte(unsigned char data)
{
//Clearing the interrupt flag
PIR1bits.SSPIF = 0;
//Shifting data to SSPBUF register
SSPBUF = data;
while(BF);
//Waiting for interrupt flag to become high or '1'
while(PIR1bits.SSPIF!=1);
//Again clearing the interrupt flag

Attique Ur Rehman (17-003) Page # 10


Embedded Systems Lab # 4 MTE-409
PIR1bits.SSPIF = 0;
}
/******************************************************************************/
unsigned char Recv_Byte(void)
{
//Clearing the interrupt flag
PIR1bits.SSPIF=0;
//Enabling the reception of data by making bit RCEN = 1
SSPCON2bits.RCEN=1;
//Waiting for completion of data reception. RCEN will be automatically cleared by hardware to indicate reception
of data
while (SSPCON2bits.RCEN);
//Waiting for interrupt flag to become high
while(!PIR1bits.SSPIF);
//Clearing the interrupt flag
PIR1bits.SSPIF=0;
//Reading the received byte
return(SSPBUF);
}
/******************************************************************************/
8) Software Implementation:

Attique Ur Rehman (17-003) Page # 11


Embedded Systems Lab # 4 MTE-409

Attique Ur Rehman (17-003) Page # 12


Embedded Systems Lab # 4 MTE-409

Attique Ur Rehman (17-003) Page # 13


Embedded Systems Lab # 4 MTE-409

9) Results:

Attique Ur Rehman (17-003) Page # 14


Embedded Systems Lab # 4 MTE-409

 Procedure:
i. Firstly, i made the functions for I2C initialization and configured its registers by using datasheet of
PIC16F877A as shown.
ii. I also read the timing diagram of I2C master mode.
iii. Then I made functions for start and stop condition of I2C communication in which we enabled the
start and stop condition by SEN (bit 0) and PEN (bit 1).
iv. Then I made functions for data transmission in which I use SSPBUF register for data write.
v. The status of ACK is written into the ACKDT bit on the falling edge of the ninth clock. If the master
receives an Acknowledge, the Acknowledge Status bit, ACKSTAT, is cleared. If not, the bit is set.
vi. After the ninth clock, the SSPIF bit is set and the master clock is suspended until the next data byte
is loaded into the SSPBUF, leaving SCL low and SDA unchanged.
vii. After this I made circuit diagram in proteus as shown in output and simulated the program.

 Conclusion:
In this lab, I have explored, learned and implemented I2C communication protocol. I have learned the
behavior of I2C communication at the beginners level and practiced it.

Attique Ur Rehman (17-003) Page # 15

You might also like