Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

I2C communication of 3 pic devices(PIC16f)

Status
Not open for further replies.

Abhilashhegde94

Member level 1
Joined
Apr 19, 2015
Messages
32
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Location
India
Activity points
276
Hey guys ,
I have coded the master device in the i2c bus.Basically my hardware consists of 4 pic16f886 devices of which 3 are slaves and 1 is master,I have coded for the master properly,now I2C coding for slave is left out,I saw many help sections for coding I2C slave in pic,My masters assigns 3 address namely 0x01,0x02,0x03 for the 3 slaves.

I use XC8 compiler.

Can anyone post a helpful code for pic16f886 slave communication,All i have to do is get the text sent on I2c bus to the particular slave and then use the Text for other purposes,Any help in this Regard will be appreciated.

If you either post the procedures that i need to use or code for I2C slave and how to initiatlize the slave as an I2C read only device etc ,it will be very helpful.Pls help ASAP

Regards
 

kanni1303

Full Member level 3
Joined
Jun 29, 2012
Messages
161
Helped
12
Reputation
24
Reaction score
11
Trophy points
1,298
Location
Chennai, Tamil Nadu, India
Activity points
2,679
Upto my knowledge the one who initiates the communication and make available the I2C path for information tranmission is master. The regarding the code, same code can be used for master and slave(if you're using same PIC) and only difference is to tell your PIC to behave as slave(wait for master to open the channel available for communication) since theres no change in buffer, but the slave address needs to be set on slave side

Kindly set the I2C control registers properly to behave as slave
 

Abhilashhegde94

Member level 1
Joined
Apr 19, 2015
Messages
32
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Location
India
Activity points
276
ya what u said is right .
Pls have a look at my master code

Code:
/*
 * File:   i2c_master.c
 * Author: JAI MATA DI
 *
 * Created on April 21, 2015, 8:00 PM
 */


#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

// CONFIG1
#pragma config "FOSC = INTRC_NOCLKOUT"          // Oscillator Selection bits (INTRC_NOCLKOUT oscillator: Internal Oscillator with No Clock Output on Pins)
#pragma config "WDTE = OFF"                     // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config "PWRTE = OFF"                    // Power-up Timer Enable bit (PWRT disabled)
#pragma config "MCLRE = ON"                     // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config "CP = OFF"                       // Code Protection bit (Program memory code protection is disabled)
#pragma config "CPD = OFF"                      // Data Code Protection bit (Data memory code protection is disabled)
#pragma config "BOREN = ON"                     // Brown Out Reset Selection bits (BOR disabled)
#pragma config "IESO = OFF"                     // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config "FCMEN = OFF"                    // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config "LVP = OFF"                      // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config "BOR4V = BOR40V"                 // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config "WRT = OFF"                      // Flash Program Memory Self Write Enable bits (Write protection off)


#define _XTAL_FREQ 8000000
#define baud_rate 9600

char UART_Init(long);
void UART_Write(unsigned char);
char UART_TX_Empty(void);
void UART_Write_Text(const char *);
char UART_Data_Ready(void);
char UART_Read(void);
unsigned char * UART_Read_Text(void);
unsigned char getch(void);
unsigned char getche(void);

//Delay functions
void delay_us(unsigned int);
void delay_ms(unsigned int);
void delay1ms(void);


//I2C functions
void I2C_init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Write(unsigned char);
unsigned char I2C_Read(char);


//I2C Constants
#define ACK	1		//ACK required for page R/W
#define NO_ACK	0		//NO ACK for byte R/W
#define MEMADD_8_16 1	//MEM Address 8bit-0/16bit-1
#define EOS 0x00		//End of String NULL

//bit IC2_ack;
//bit ACK_Bit;
bit IC2_ack;
//Serial EEPROM pins
//#define SDA PORTCbits.PORTC4;		// connect to SDA pin (Data) of 24Cxx
//#define SCL PORTCbits.PORTC3;		// connect to SCL pin (Clock) of 24Cxx

void main(void)
{

   const unsigned char * arr1 = "taking in the text \r\n";

   const unsigned char *arr2="\r\nEnter your choice \r\n 1.Slave 1(Address:0x01\r\n2.Slave 2(Address:0x02)\r\n3.Slave 3(Address:0x03\r\n";
   const unsigned char *arr3= "You have entered:\r\n";
   const unsigned char *msg1="Sending to Slave 1 (Address 0x01)\r\n";
   const unsigned char *msg2="Sending to Slave 2 (Address 0x02)\r\n";
   const unsigned char *msg3="Sending to Slave 3 (Address 0x03)\r\n";
   const unsigned char *msg4="address sent\r\n";
   const unsigned char *msg5="data sent\r\n";
 //  const unsigned char *err="No message will be sent since no slave no entered\r\n";
  // const unsigned char *err1="Error in I2c slave sending (Fault problems:Resend)\r\n";
   const unsigned char *fin="Closing Communication\r\n";
   const unsigned char *msgm="You have entered choice number\r\n";
   unsigned char choice;

   unsigned char *is;

   OSCCONbits.IRCF = 0x07;  // Configure Internal OSC for 8MHz Clock



    while(!OSCCONbits.HTS);   // Wait Until Internal Osc is Stable

    INTCON=0;   // purpose of disabling the interrupts.

    UART_Init(baud_rate);
    delay_ms(500);
    I2C_init();
    while(1)
    {
        UART_Write_Text(arr1);
        I2C_Start();
  //receive the characters until ENTER is pressed (ASCII for ENTER = 13)

         is=UART_Read_Text();
         UART_Write_Text(arr3);
         UART_Write_Text(is);
         UART_Write_Text(arr2);
         choice=UART_Read();
         UART_Write_Text(msgm);
         UART_Write(choice);

    switch(choice)
    {
        case 0x31:

            {

              UART_Write_Text(msg1);
              I2C_Write(0x01);        //device address
              UART_Write_Text(msg4);
              I2C_Write('a');         //data byte
              UART_Write_Text(msg5);
              break;
            }

        case 0x32:

            {
              UART_Write_Text(msg2);
              I2C_Write(0x02);        //device address
              UART_Write_Text(msg4);
              I2C_Write('b');         //data byte
              UART_Write_Text(msg5);
              break;
            }

       case 0x33:
            {
              UART_Write_Text(msg3);
              I2C_Write(0x03);          //device address
              UART_Write_Text(msg4);
              I2C_Write('c');           //data byte
              UART_Write_Text(msg5);
              break;
           }

       // default:
            // UART_Write_Text(err);

    }
    //Choice entered data sent respectively to slaves now stop
    //i2c_SendAcknowledge(I2C_LAST);
    I2C_Stop();

    UART_Write_Text(fin);

    }
}


/*
I2c EEPROM Modules
*/

void I2C_init()
{
    TRISCbits.TRISC3 = 0;  //direction register SCL
    TRISCbits.TRISC4 = 0; //direction register SDA
}

//-------------------------------
// start I2C
//H-L transition of SDA with SCL high is a start condition
//-------------------------------
void I2C_Start()
{
        PORTCbits.RC4 = 1;
	PORTCbits.RC3 = 1;
	delay_us(2);		//setup time
	PORTCbits.RC4 = 0;
	delay_us(5);
	PORTCbits.RC3 = 0;			//Release clock
	delay_us(2);
}

//-------------------------------
// stop I2C
//L-H transition of SDA with SCL high is a stop condition
//-------------------------------
void I2C_Stop()
{
	PORTCbits.RC4 = 0;
	delay_us(2);
	PORTCbits.RC3 = 1;
	delay_us(5);
	PORTCbits.RC4 = 1;
	delay_us(2);
	//SCL = 0;			//Release clock

}

//-------------------------------
// Write I2C
//First setup the bit from data and then positive edge clock the data in to the eeprom
//-------------------------------
void I2C_Write(unsigned char Data)
{
	unsigned char i;
	//bit IC2_ack;
	IC2_ack = 1;
	for (i=0;i<8;i++)
	{
        PORTCbits.RC4 = (Data & 0x80) ? 1:0; //Getting bits from DATA MSB first
		delay_us(1);
		PORTCbits.RC3=1;
		delay_us(5);
		PORTCbits.RC3=0;
		Data<<=1;
	}
	//Reading ninth bit ACK
	PORTCbits.RC4 = 1; 	//Release SDA for ACK
	delay_us(2);
  	PORTCbits.RC3 = 1;
	delay_us(4);
	IC2_ack = PORTCbits.RC4;
	PORTCbits.RC3 = 0;

}

//-------------------------------
// Read I2C
//-------------------------------
unsigned char I2C_Read(char ACK_Bit)
{

    unsigned char i,Data=0;

    PORTCbits.RC4 = 1;			// making SDA as input pin for microcontroller
	for (i=0;i<8;i++)
	{
		delay_us(3);
		PORTCbits.RC3   = 1;
		delay_us(2);
		Data<<= 1;
		Data  = (Data | PORTCbits.RC4);
		PORTCbits.RC3   = 0;
	}

 	if (ACK_Bit == 0x01)
		PORTCbits.RC4 = 0; 	// Send ACK
	else
		PORTCbits.RC4 = 1; 	// Send NO ACK

	delay_us(2);
	PORTCbits.RC3 = 1;
	delay_us(4);
	PORTCbits.RC3 = 0;

	return Data;
}

//Delay routines

void delay_us(unsigned int i)
{
	for (;i!=0x00;i--);
}

void delay_ms(unsigned int i)
{
	for(;i!=0x00;i--)
		delay1ms();
}

void delay1ms(void)
{
	unsigned int j = 130;
	for (;j!=0x00;j--);
}

  char UART_Init(long baudrate)
{
  unsigned int x;
  x = (_XTAL_FREQ - baudrate*64)/(baudrate*64); //SPBRG for Low Baud Rate
  if(x>255) //If High Baud Rate required
  {
    x = (_XTAL_FREQ - baudrate*16)/(baudrate*16); //SPBRG for High Baud Rate

    BRGH = 1; //Setting High Baud Rate
    SPBRG = x; //Writing SPBRG register
    SYNC = 0; //Selecting Asynchronous Mode
    SPEN = 1; //Enables Serial Port
//    TRISC7 = 1;   //Not Needed Or Recommended
//    TRISC6 = 1;   //Not Needed Or Recommended
    CREN = 1; //Enables Continuous Reception
    TXEN = 1; //Enables Transmission
  }
  if(x<256)
  {
    BRGH = 0; //Setting High Baud Rate
    SPBRG = x; //Writing SPBRG register
    SYNC = 0; //Selecting Asynchronous Mode
    SPEN = 1; //Enables Serial Port
//    TRISC7 = 1;   //Not Needed Or Recommended
//    TRISC6 = 1;   //Not Needed Or Recommended
    CREN = 1; //Enables Continuous Reception
    TXEN = 1; //Enables Transmission
    return 1;
  }
  return 0;
}

void UART_Write(unsigned char data)
{
  while(!PIR1bits.TXIF);
  while(!TRMT); //Waiting for Previous Data to Transmit completly
  TXREG = data; //Writing data to Transmit Register, Starts transmission
}

char UART_TX_Empty()
{
  return TRMT; //Returns Transmit Shift Status bit
}

void UART_Write_Text(const char *text)
{
  int i;
  for(i=0;text[i]!='\0';i++)
    UART_Write(text[i]);

}

//recive part
char UART_Data_Ready()
{
  return RCIF;
}

char UART_Read()
{
  while(!RCIF); //Waits for Reception to complete
  return RCREG; //Returns the 8 bit data
}

unsigned char * UART_Read_Text()
{
  unsigned const char *a="Keyed in \r\n";
  unsigned static char string[20];
  unsigned char x, i = 0;

//receive the characters until ENTER is pressed (ASCII for ENTER = 13)
while((x = UART_Read()) != 13)
{
 //and store the received characters into the array string[] one-by-one
string[i++] = x;
}

//insert NULL to terminate the string
string[i] = '\0';
UART_Write_Text(a);

//return the received string
return(string);
}

void putch(unsigned char byte)
{
    /* output one byte */
    while(!TXIF)    /* set when register is empty */
        continue;
    TXREG = byte;
}

unsigned char getch()
{
    /* retrieve one byte */
    while(!RCIF)    /* set when register is not empty */
        continue;
    return RCREG;
}

unsigned char getche(void)
{
    unsigned char c;
    putch(c = getch());
    return c;
}
no header file is included here .Everything is done in the main c file itself.

The master according to me is working fine and i am getting required UART text outputs whereas the slave code which is described here is what i am not sure about,since it builds fine but i dont get the text i transmit from the master to the slave in I2C bus communication.
My project deadline is approaching and if anyone can pls help in rectifying the slave code then i would be very grateful ,Pls do it ASAP, :(

Slave code also contains no headers since everything is defined within.
Code:
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

// CONFIG1
#pragma config "FOSC = INTRC_NOCLKOUT"          // Oscillator Selection bits (INTRC_NOCLKOUT oscillator: Internal Oscillator with No Clock Output on Pins)
#pragma config "WDTE = OFF"                     // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config "PWRTE = OFF"                    // Power-up Timer Enable bit (PWRT disabled)
#pragma config "MCLRE = ON"                     // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config "CP = OFF"                       // Code Protection bit (Program memory code protection is disabled)
#pragma config "CPD = OFF"                      // Data Code Protection bit (Data memory code protection is disabled)
#pragma config "BOREN = ON"                     // Brown Out Reset Selection bits (BOR disabled)
#pragma config "IESO = OFF"                     // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config "FCMEN = OFF"                    // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config "LVP = OFF"                      // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config "BOR4V = BOR40V"                 // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config "WRT = OFF"                      // Flash Program Memory Self Write Enable bits (Write protection off)


#define _XTAL_FREQ 8000000
#define baud_rate 9600

unsigned char datain;
unsigned char rxbuffer[20];
unsigned char txbuffer[20];
unsigned char rxbufferindex =0,txbufferindex=0;
unsigned char rxbufferlen=1,txbufferlen=1;
unsigned char read_count=0,datain=0,write_data=0;

//Delay functions
void delay_us(unsigned int);
void delay_ms(unsigned int);
void delay1ms(void);


char UART_Init(long);
void UART_Write(unsigned char);
char UART_TX_Empty(void);
void UART_Write_Text(const char *);
char UART_Data_Ready(void);
char UART_Read(void);
unsigned char * UART_Read_Text(void);
unsigned char getch(void);
unsigned char getche(void);

void I2C_init(void);
void I2C_slave(void);
void I2C_write(void);
void I2C_read(void);
void I2C_exit(void);

void main()
{
    const char *msg1="/r/nWaiting for Data from Master";
    const char *t1="/r/nWaiting for Data from Masterhdhhd";

    OSCCONbits.IRCF = 0x07;  // Configure Internal OSC for 8MHz Clock

    while(!OSCCONbits.HTS);   // Wait Until Internal Osc is Stable

    UART_Init(baud_rate);
    delay_ms(500);
    UART_Write_Text(msg1);
    I2C_init();
     while(1)
     {
         
         if(PIR1bits.SSPIF == 0)
          {
            UART_Write_Text(t1);
            I2C_slave();
          }

        SSPCONbits.SSPOV =0;
        SSPCONbits.WCOL = 0;
        write_data = 0;
     }
}

void I2C_init()
{
    TRISCbits.TRISC3 = 1;  //direction register SCL as input pin
    TRISCbits.TRISC4 = 1; //direction register SDA as input pin
    SSPADD = 0X01; //your device address
    SSPCON = 0X36; //SSPEN =1 and set i2c to slave mode with 7 bit address
    SSPSTAT =0;
    PIE1bits.SSPIE = 1;
    PIR1bits.SSPIF = 0;
    rxbufferindex = 0;
    txbufferindex = 0;
}

void I2C_slave()
{
    const char *msg2="/r/nchecking for appropriate flag";
    const char *msg3="/r/nwriting text receive from master";
    const char *msg4="/r/nmaster is reading from slave";
    const char *msg5="/r/nbuffer full";

    UART_Write_Text(msg2);

    SSPIF =1;
    if(SSPSTATbits.R_W == 1)
    {
        UART_Write_Text(msg4);
        I2C_read();
    }
    if(SSPSTATbits.BF == 1)
    {
        UART_Write_Text(msg5);
        I2C_exit();
    }
    if(SSPSTATbits.D_A == 1)
    {
        UART_Write_Text(msg3);
        I2C_write();
    }
    if(SSPBUF != 0x01)
    {
        I2C_exit();
    }
    read_count = 0;
    
    I2C_exit();
    
}

void I2C_exit()
{
    return;
}

//Delay routines

void delay_us(unsigned int i)
{
	for (;i!=0x00;i--);
}

void delay_ms(unsigned int i)
{
	for(;i!=0x00;i--)
		delay1ms();
}

void delay1ms(void)
{
	unsigned int j = 130;
	for (;j!=0x00;j--);
}


void I2C_write()
{
 datain = SSPBUF;
 UART_Write(datain);
 rxbuffer[rxbufferindex] = datain;
 rxbufferindex = rxbufferindex +1;
 if(rxbufferindex == rxbufferlen)
 {
     write_data = 1;
     rxbufferindex = 0;
 }
 I2C_exit();
}

void I2C_read()
{
   if(SSPSTATbits.D_A == 0)
   {
       txbufferindex = 0;
   }
   
   while(SSPSTATbits.BF)
   {
       while(SSPCONbits.WCOL)
       {
         SSPCONbits.WCOL = 0;
         SSPBUF = txbuffer[txbufferindex];
       }
       SSPCONbits.CKP = 1;
       txbufferindex = txbufferindex + 1;
       if(txbufferindex = txbufferlen)
       {
           txbufferindex = 0;
       }
   }
   
   I2C_exit();
    
}


  char UART_Init(long baudrate)
{
  unsigned int x;
  x = (_XTAL_FREQ - baudrate*64)/(baudrate*64); //SPBRG for Low Baud Rate
  if(x>255) //If High Baud Rate required
  {
    x = (_XTAL_FREQ - baudrate*16)/(baudrate*16); //SPBRG for High Baud Rate

    BRGH = 1; //Setting High Baud Rate
    SPBRG = x; //Writing SPBRG register
    SYNC = 0; //Selecting Asynchronous Mode
    SPEN = 1; //Enables Serial Port
//    TRISC7 = 1;   //Not Needed Or Recommended
//    TRISC6 = 1;   //Not Needed Or Recommended
    CREN = 1; //Enables Continuous Reception
    TXEN = 1; //Enables Transmission
  }
  if(x<256)
  {
    BRGH = 0; //Setting High Baud Rate
    SPBRG = x; //Writing SPBRG register
    SYNC = 0; //Selecting Asynchronous Mode
    SPEN = 1; //Enables Serial Port
//    TRISC7 = 1;   //Not Needed Or Recommended
//    TRISC6 = 1;   //Not Needed Or Recommended
    CREN = 1; //Enables Continuous Reception
    TXEN = 1; //Enables Transmission
    return 1;
  }
  return 0;
}

void UART_Write(unsigned char data)
{
  while(!PIR1bits.TXIF);
  while(!TRMT); //Waiting for Previous Data to Transmit completly
  TXREG = data; //Writing data to Transmit Register, Starts transmission
}

char UART_TX_Empty()
{
  return TRMT; //Returns Transmit Shift Status bit
}

void UART_Write_Text(const char *text)
{
  int i;
  for(i=0;text[i]!='\0';i++)
    UART_Write(text[i]);

}

//recive part
char UART_Data_Ready()
{
  return RCIF;
}

char UART_Read()
{
  while(!RCIF); //Waits for Reception to complete
  return RCREG; //Returns the 8 bit data
}

unsigned char * UART_Read_Text()
{
  unsigned const char *a="Keyed in \r\n";
  unsigned static char string[20];
  unsigned char x, i = 0;

//receive the characters until ENTER is pressed (ASCII for ENTER = 13)
while((x = UART_Read()) != 13)
{
 //and store the received characters into the array string[] one-by-one
string[i++] = x;
}

//insert NULL to terminate the string
string[i] = '\0';
UART_Write_Text(a);

//return the received string
return(string);
}

void putch(unsigned char byte)
{
    /* output one byte */
    while(!TXIF)    /* set when register is empty */
        continue;
    TXREG = byte;
}

unsigned char getch()
{
    /* retrieve one byte */
    while(!RCIF)    /* set when register is not empty */
        continue;
    return RCREG;
}

unsigned char getche(void)
{
    unsigned char c;
    putch(c = getch());
    return c;
}
Pls do it asap--
Changing the whole code(Master or Slave or both) to get the appropriate output is also fine by me,but with a little explanation it would be better.

Regards and thanx in advance
 
Last edited:

bigdogguru

Administrator
Joined
Mar 12, 2010
Messages
9,831
Helped
2,348
Reputation
4,690
Reaction score
2,273
Trophy points
1,413
Location
Southwest, USA
Activity points
62,488
The following Microchip application note is almost exactly what you are requesting:


AN736 Microchip Appnote - An I2C Network Protocol for Environmental Monitoring


The appnote details how to network several PIC16Fs using the I2C protocol in a Master/Slave configuration, it also includes complete source code in HiTech PIC Compiler which was the predecessor of the XC8 Compiler. The master communicates data/status using its UART in RS-232 serial configuration with a terminal or PC.

You should be able to customize it to fit your requirements.

BigDog
 

Status
Not open for further replies.
Toggle Sidebar

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top