Tuesday 20 October 2015

PIC12F675 I2C [TWO WIRE COMMUNICATION]





#include<pic.h>
#include<htc.h>
#define __PIC12F675_H                    //header file for ic
__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & CP_OFF & CPD_OFF);  //config word
#define _XLAT_FREQ 4000000             //define cpu frequency

void delay(unsigned int i)
{
while(i--);
}




// Define i2c pins
#define SDA GP4 // Data pin for i2c
#define SCK GP5 // Clock pin for i2c
#define SDA_DIR TRISIO4 // Data pin direction
#define SCK_DIR TRISIO5 // Clock pin direction

#define DataPinADCMask ANS3 // It is attached on GP4(AN3) pin
#define ClockPinADCMask ANS3 // It is not attached on any ADC pin



// Define macros
#define Set_SDA_Low SDA_DIR = 0
#define Set_SDA_High SDA_DIR = 1
#define Set_SCK_Low SCK_DIR = 0
#define Set_SCK_High SCK_DIR = 1



void InitI2C(void)
{
DataPinADCMask  = 1; // Make analog output
ClockPinADCMask = 1; // Make analog output

// Make SDA and SCK pins input initially
SDA_DIR = 1;
SCK_DIR = 1;

// Write zero in output register of SDA and SCK pin
SDA = 0;
SCK = 0;
}


void I2C_Start(void)
{
SDA = 0; // Write zero in output register
SCK = 0; // of SDA and SCK pin

Set_SCK_High; // Make SCK pin high
Set_SDA_High; // Make SDA pin High
delay(100); // Half bit delay
Set_SDA_Low; // Make SDA Low
delay(100); // Half bit delay
}



void I2C_ReStart(void)
{
Set_SCK_Low; // Make SCK pin low

delay(100); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_High; // Make SDA pin High

    delay(100); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
delay(100); // 1/4 bit delay
Set_SDA_Low; // Make SDA Low
delay(100); // 1/4 bit delay
}



void I2C_Send_ACK(void)
{
Set_SCK_Low; // Make SCK pin low
delay(100); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_Low; // Make SDA Low
delay(100); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
delay(100); // Half bit delay
}



void I2C_Stop(void)
{
Set_SCK_Low; // Make SCK pin low

delay(100); // Data pin should change it's value,
// when it is confirm that SCK is low
Set_SDA_Low; // Make SDA pin low

delay(100); // 1/4 bit delay
Set_SCK_High; // Make SCK pin high
delay(100); // 1/4 bit delay
Set_SDA_High; // Make SDA high
delay(100); // 1/4 bit delay
}



bit I2C_Write_Byte(unsigned char Byte)
{
static bit ACK = 0;

unsigned char i; // Variable to be used in for loop

for(i=0;i<8;i++) // Repeat for every bit
{
Set_SCK_Low; // Make SCK pin low

delay(100); // Data pin should change it's value,
// when it is confirm that SCK is low

if((Byte<<i)&0x80)  // Place data bit value on SDA pin
Set_SDA_High; // If bit is high, make SDA high
else // Data is transferred MSB first
Set_SDA_Low; // If bit is low, make SDA low

delay(100); // Toggle SCK pin
Set_SCK_High; // So that slave can
delay(100); // latch data bit
    }

// Get ACK from slave
Set_SCK_Low;
    Set_SDA_High;
    delay(100);
    Set_SCK_High;
    delay(100);

DataPinADCMask = 0; // Make digital input
ACK = SDA; // Read data pin status
DataPinADCMask = 1; // Make analog output

return ACK;
}


unsigned char I2C_Read_Byte(void)
{
unsigned char i, RxData = 0;

for(i=0;i<8;i++)
{
Set_SCK_Low; // Make SCK pin low
Set_SDA_High; // Don't drive SDA
delay(100); // Half bit delay
Set_SCK_High; // Make SCK pin high
delay(100); // 1/4 bit delay
DataPinADCMask = 0; // Make digital input
RxData = RxData|(SDA<<(7-i)); // Captured received bit
DataPinADCMask = 1; // Make analog output
delay(100); // 1/4 bit delay
}

    return RxData; // Return received byte
}


void InitCCT(void)
{
ANSEL  = 0x00;       // Set ports as digital I/O, not analog input
ADCON0 = 0x00; // Shut off the A/D Converter
CMCON  = 0x07; // Shut off the Comparator
VRCON  = 0x00;     // Shut off the Voltage Reference
}





void main()
{
unsigned char RxByte = 0;

InitCCT(); // Turn off ADC and comparator to make pins digital IOs
InitI2C(); // Initialize i2c pins

I2C_Start(); // Send start bit on i2c
I2C_Write_Byte(0xA0); // Send 0xA0 on i2c
RxByte = I2C_Read_Byte(); // Read value from i2c
I2C_Send_ACK(); // Send ACK bit on i2c
I2C_Stop(); // Send stop bit on i2c

while(1)
{
}
}

No comments:

Post a Comment