PIC 2 PIC Master/Slave Communication using I2C... Enjoy

General discussion on mikroC.
Author
Message
TomSSS
Posts: 6
Joined: 28 Aug 2006 23:27

PIC 2 PIC Master/Slave Communication using I2C... Enjoy

#1 Post by TomSSS » 06 Dec 2006 05:04

Hi all, here is some simple code for Master/Slave I2C projects. I can't take all of the credit for writing this. I used mB and mP code/methods that I found on the forum and translated it into this. Feel free to comment, but I might not be quick to respond because I only get on here about 1-2 times a week.

Here's the Master code

Code: Select all

/*
 * Project name:
     Master
 * Description:
     Master control for PIC 2 PIC I2C Communication
 * Configuration:
     MCU:             PIC16F876A
     SW:              mikroC v6.0
 * NOTES:
*/

//------------------------------------------------------------------------------
const Slave_Addy = 0x69;

void send(unsigned short send_data){
  I2C_Init(100000);
  I2C_Start();
  I2C_Wr(Slave_Addy);
  I2C_Wr(send_data);
  I2C_Stop();
}

unsigned short read(){
  unsigned short read_data;
  I2C_Init(100000);
  I2C_Start();
  I2C_Wr(Slave_Addy + 1);
  read_data = I2C_Rd(0);
  delay_ms(100);
  I2C_Stop();
  return read_data;
}

void main(){
 // Main program code place here.  
 // Use sub-routine "send" to send data to slave.
 // Use "read" to read data from slave.
}
Here's the Slave code

Code: Select all

/*
 * Project name:
     Slave
 * Description:
     Slave code for PIC 2 PIC I2C Communication
     Write data from Master to PORTB
     Send PORTC data to Master
 * Configuration:
     MCU:             PIC16F876A
     SW:              mikroC v6.0
 * NOTES:
*/

//------------------------------------------------------------------------------
const Addy = 0x69;                    // set I2C device address
const Delay_Time = 250;               // port check delay
//------------------------------------------------------------------------------
//                      Global Processing Variables
//------------------------------------------------------------------------------
unsigned short j;                      // just dummy for buffer read
unsigned short rxbuffer;               // 
unsigned short tx_data;                //
//------------------------------------------------------------------------------
void Init(){
  ADCON1 = 0;                          // All ports set to digital
  TRISA = 0;                           // Set PORTA as output
  TRISB = 0;                           // Set PORTB as output
  TRISC = 0xFF;                        // Set PORTC as input
  SSPADD =  Addy;                      // Get address (7bit). Lsb is read/write flag
  SSPCON = 0x36;                       // Set to I2C slave with 7-bit address
  PIE1.SSPIF = 1;                      // enable SSP interrupts
  INTCON = 0xC0;                       // enable INTCON.GIE
}
//------------------------------------------------------------------------------
void interrupt(){                      // I2C slave interrupt handler
  if (PIR1.SSPIF == 1){                // I2C Interrupt
    PIR1.SSPIF = 0;                    // reset SSP interrupt flag

    //transmit data to master
    if (SSPSTAT.R_W == 1){             // Read request from master
      SSPBUF = tx_data;                // Get data to send
      SSPCON.CKP = 1;                  // Release SCL line
      j = SSPBUF;                      // That's it
      return;
    }
    if (SSPSTAT.BF == 0){              // all done,
      j = SSPBUF;                      // Nothing in buffer so exit
      return;
    }

    //recieve data from master
    if (SSPSTAT.D_A == 1){             // Data [not address]
      rxbuffer = SSPBUF;               // get data
      j = SSPBUF;                      // read buffer to clear flag [address]
      return;
    }
  }
  j = SSPBUF;                              // read buffer to clear flag [address]
}
//------------------------------------------------------------------------------
void main(){
  Init();
  while(1){
    PORTB   = rxbuffer;
    tx_data = PORTC;
    Delay_ms(Delay_Time);
  }
}
Enjoy,
Tom

User avatar
zristic
mikroElektronika team
Posts: 6608
Joined: 03 Aug 2004 12:59
Contact:

Re: PIC 2 PIC Master/Slave Communication using I2C... Enjoy

#2 Post by zristic » 06 Dec 2006 09:04

Thanks.

gedo
Posts: 53
Joined: 02 Aug 2006 16:42

#3 Post by gedo » 07 Dec 2006 13:48

thanx. but i send data from master do not read on slave portB.
master PortC.F3 to Slave PortC.F4 & M PortC.F4 To S PortC.F3 is right shematic.

TomSSS
Posts: 6
Joined: 28 Aug 2006 23:27

#4 Post by TomSSS » 08 Dec 2006 01:08

gedo wrote:thanx. but i send data from master do not read on slave portB.
master PortC.F3 to Slave PortC.F4 & M PortC.F4 To S PortC.F3 is right shematic.
I'm not sure if you are asking a question here or trying to state something but I'll try to explain a little bit more.

You send serial data from the Master to the Slave using these two lines.
PORTC.F3 is the SCL line
PORTC.F4 is the SDA line


The pin mapping (schematic) should be:
Master PORTC.F3 -> Slave PORTC.F3
Master PORTC.F4 -> Slave PORTC.F4

Those are the I2C lines on the 16F876A.

The slave program takes the serial data from the master, 8-bits, and sets the PORTB output of the slave device based on this.

Example:
-------------
The master sends the following data stream 00110011
The slave would set its PORTB = 00110011

If the slave recieves a "read" command the slave will read its PORTC and compile this into serial data to be sent via I2C to the master.

Note: Bits 3 and 4 of the PORTC data sent from the slave to the master should be ignored by the master because these are the I2C lines.

Remoeggel
Posts: 19
Joined: 12 Aug 2008 07:08

No Interrupt in I2C slave

#5 Post by Remoeggel » 12 Aug 2008 07:18

Hello Tom

I try to put your code in my program for a slave I2C pic.
But i get never a interrupt.
Do you know what could be the problem?

Code if interrupt has occured:

Code: Select all

void interrupt(){
   
    if (PIR1.SSPIF = 1){
    
        static unsigned short reg = SERVO_REG_MAX;
    
        PIR1.SSPIF = 0;
        PORTD.F0 = 1;
       
        //transmit data to master
        if (SSPSTAT.R_W == 1){             // Read request from master
          if (reg < SERVO_REG_MAX){
             SSPBUF = servo_register[reg]; // Get data to send
             reg = SERVO_REG_MAX;
             SSPCON.CKP = 1;               // Release SCL line
             j = SSPBUF;
          }                                // That's it
          return;
        }
        if (SSPSTAT.BF == 0){              // all done,
          j = SSPBUF;                      // Nothing in buffer so exit
          return;
        }

        //recieve data from master
        if (SSPSTAT.D_A == 1){             // Data [not address]
          //PORTD.F0 = 0;
          if (reg < SERVO_REG_MAX){
               servo_register[reg] = SSPBUF;  // get data
               j = SSPBUF;                    // read buffer to clear flag [address]
               reg = SERVO_REG_MAX;
          }
          else {
               reg = SSPBUF;
               j = SSPBUF;                    // read buffer to clear flag [address]
          return;
        }
        }
        j = SSPBUF;                              // read buffer to clear flag [address]
       
    }
}

Code for init:

Code: Select all

//* iniyialisieren des I2C Interface *//
    SSPADD =  0xC2;                      // Get address (7bit). Lsb is read/write flag
    SSPCON = 0x34;                       // Set to I2C slave with 7-bit address
    
    //* Interrupts erlauben *//
    INTCON.GIE = 1;
    INTCON.PEIE = 1;
    PIE1.SSPIE = 1;                      // enable SSP interrupts
    PIE1.TMR1IE = 1;
    PIR1.TMR1IF = 0;
    PIR1.SSPIF = 0;

Best regards

Remo Hug

prancius
Posts: 148
Joined: 26 Sep 2007 21:52

Thank you a lot

#6 Post by prancius » 12 Aug 2008 10:27

Thank you a lot for example.

It is exactly what i need. I will chect it via proteus soon.

Regards,
Pranas

prancius
Posts: 148
Joined: 26 Sep 2007 21:52

Error

#7 Post by prancius » 12 Aug 2008 12:16

Strange but i have some problem.

I am using 4k7 external rezistors and 8MGhz frequency


Image

Trying to find out the problem

Remoeggel
Posts: 19
Joined: 12 Aug 2008 07:08

#8 Post by Remoeggel » 12 Aug 2008 14:15

Hi Pranas

I use the PIC 16F877A (8MHz) with the EasyPIC5-Board.

Regards,
Remo

prancius
Posts: 148
Joined: 26 Sep 2007 21:52

about second pic

#9 Post by prancius » 12 Aug 2008 15:05

Hello,

Can you give some explanation how you connected second PIC16F877A?

Thank you
Pranas

MasterBlaster
Posts: 165
Joined: 25 Oct 2007 22:22
Location: Wuppertal, Germany, Earth... :-)
Contact:

Re: about second pic

#10 Post by MasterBlaster » 12 Aug 2008 15:17

prancius wrote:Can you give some explanation how you connected second PIC16F877A?
Hi prancius,

simply connect 8):

SDA (Master RC4) <==> SDA (RC4 Slave)
SCL (Master RC3) <==> SCL (RC3 Slave)

Don't forget GND connected to all devices as like as Master and Slave (with resistors from SDA and SCL to Vcc). :roll:

Only the "Master" is the one and only who determines who has anything to send and/or receive. :shock:
so long,
MasterBlaster.

Using: EasyPIC4 HW. Rev. 1.03, LCD- & GLCD Display, NetWork and SD/MMC Adapter,
reg. MikroC Pro for PIC 2009, PIC 16F877A, 18F452 and 18F4685 with 8/20 MHz Xtal.

Remoeggel
Posts: 19
Joined: 12 Aug 2008 07:08

#11 Post by Remoeggel » 12 Aug 2008 15:41

Hello Pranas

I use the "PC to I2C-Bus Adapter" as Master, not a PIC.

(http://www.shop.robotikhardware.de/shop ... ucts_id=68)

Best Regards

Remo

prancius
Posts: 148
Joined: 26 Sep 2007 21:52

So

#12 Post by prancius » 12 Aug 2008 15:58

So as i understand one pic you a placed on easypic5 second on some dev board. And you connected like this?

Are you using external pull ups or just pull up jumper on port c?

Image

Thank you
Pranas

Remoeggel
Posts: 19
Joined: 12 Aug 2008 07:08

#13 Post by Remoeggel » 12 Aug 2008 17:08

No.
I the PIC on the Board (EasyPic5) is the slave.

I send data from a VB-Programm to the pic over the "PC to I2C-Bus Adapter".

Link to "PC to I2C-Bus Adapter":
http://www.shop.robotikhardware.de/shop ... ucts_id=68

Best Regards

Remo

TomSSS
Posts: 6
Joined: 28 Aug 2006 23:27

Re: No Interrupt in I2C slave

#14 Post by TomSSS » 14 Aug 2008 01:34

Remoeggel wrote:Hello Tom

I try to put your code in my program for a slave I2C pic.
But i get never a interrupt.
Do you know what could be the problem?

Code if interrupt has occured:

Code: Select all

void interrupt(){
   
    if (PIR1.SSPIF = 1){
    
 
I believe this should be changed to

Code: Select all

void interrupt(){
   
    if (PIR1.SSPIF == 1){
    
 
Give it a try and let me know

Remoeggel
Posts: 19
Joined: 12 Aug 2008 07:08

It works now!!!

#15 Post by Remoeggel » 14 Aug 2008 14:09

Hello Tom

It works now.
The problem was a false value in the register SSPCON.
:oops: :x :oops:

thanks for all

Remo

Post Reply

Return to “mikroC General”