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

General discussion on mikroC.
Author
Message
programmer5
Posts: 69
Joined: 28 Jan 2012 06:50
Location: Pakistan
Contact:

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

#31 Post by programmer5 » 02 Mar 2012 09:07

my single pic i2c master and 5 slaves are working fine.
http://youtu.be/SEOJJxSO-wU

vishaletm
Posts: 50
Joined: 26 Jan 2012 05:09
Contact:

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

#32 Post by vishaletm » 01 Jun 2012 18:32

programmer5 wrote:my single pic i2c master and 5 slaves are working fine.
http://youtu.be/SEOJJxSO-wU

Could you please share the code..?

Regards.
Vishal
http://microcontrollerprojects00.blogspot.com/
ARM, PIC , AVR, 8051 Projects/Tutorials (MikroC)
If you get, give. If you learn, teach.

Co-Fi
Posts: 23
Joined: 27 Aug 2012 10:35

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

#33 Post by Co-Fi » 24 Oct 2013 20:40

Hello!

I'm also trying to use I2C master-slave comm between two PIC16F1823 microcontrollers, but i never get interrupt. Can you please check my codes, and help me out?
Thanks a lot!

Code: Select all

/***********************
*TÁJÉKOZÓDÁSI STRATÉGIA*
* ÉS IRÁNYÍTÓ ESZKÖZ   *
*     FEJLESZTÉSE      *
*LÁTÁSSÉRÜLTEK SZÁMÁRA *
*  PIC16f1823 @ 32MHz  *
* 2013 Erdélyi Viktor  *
*        MASTER        *
***********************/
// Slave address
const Slave = 0x69;

// 8 bit variables
typedef unsigned char uint8;

// flags
bit oldstate;
bit echoold;

// Variables
uint8 Dist1;                             //Distance and azimuth variables
uint8 Pot1;
uint8 Pot2;
uint8 Dist2;
uint8 Pitch;

// denominate I/O bits

sbit Echo at RC2_bit;
sbit Echo_d at TRISC2_bit;
sbit Trig at RA2_bit;
sbit Trig_d at TRISA2_bit;

void Tone1() {
     Sound_Play(500, 20);               // Frequency = 659Hz, duration = 1000ms
     //Sound_Play(Pitch, 20);           // Uncomment to modulate pitch
}

void hardinit(void) {
     ANSELA  = 0;                       // Configure AN pins as digital
     ANSELC = 0;
     C1ON_bit = 0;                      // Disable comparators
     C2ON_bit = 0;
     APFCON = 0b10000100;
     Echo_d = 1;                        // Init I/O ports
     Trig_d = 0;
     Trig = 0;
     UART1_Init(9600);                  // Initialize UART module at 9600 bps
     Delay_ms(100);                     // Wait for UART module to stabilize
     Sound_Init(&PORTC, 4);             // Init sound
     PWM1_Init(25000);                  // Initialize PWM1 module at 25KHz
     PWM1_Start();                      // Start PWM1
     oldstate = 0;                      // Init flags
     echoold = 0;
     Dist1 = 0;                         // Initialize variables
     Dist2 = 250;
     Pot1 = 0;
     Pot2 = 0;
     Pitch = 400;
}


void send(unsigned short send_data){    // Sub for triggering slave
  I2C1_Init(100000);
  I2C1_Start();
  I2C1_Wr(Slave);
  I2C1_Wr(0xFF);
  I2C1_Stop();
}

unsigned short read(){                  // Sub for data request
  unsigned short read_data;
  I2C1_Init(100000);
  I2C1_Start();
  I2C1_Wr(Slave + 1);
  Dist2 = I2C1_Rd(0);
  Pot1 =  I2C1_Rd(0);
  Pot2 =  I2C1_Rd(0);
  delay_ms(100);
  I2C1_Stop();
  return read_data;
}

void distM(void) {                      // Subroitune for distance measuring
     Dist2 = 255;
     echoold = 0;
     oldstate = 0;
     Trig = 1;
     oldstate = 1;
     delay_us(11);
     Trig = 0;
     if (oldstate == 1){
        while (echoold == 0){
              if (Echo == 1){
                 echoold = 1;
                 while (Echo == 1) {
                       delay_us(100);   // 17 mm precision
                       Dist2 --;
                       //Pitch = Dist2*5+400;    // +17 mm => +5 Hz (uncomment to modulate Pitch)
                       }
                 }
              }
        }
     }

void main() {
     hardinit();
     while(1) {

     send;                            // Send trigger to slave
     distM();                           // Measuring distance
     PWM1_Set_Duty(dist2);              // Set volume
     Tone1();
     //read;                            // Request data from slave
     //UART1_Write(Dist1);              // Data transmission to PC
     UART1_Write(Dist2);
     //UART1_Write(Pot1);
     //UART1_Write(Pot2);
     
     }
}
The Slave is:

Code: Select all

/***********************
*TÁJÉKOZÓDÁSI STRATÉGIA*
* ÉS IRÁNYÍTÓ ESZKÖZ   *
*     FEJLESZTÉSE      *
*LÁTÁSSÉRÜLTEK SZÁMÁRA *
*  PIC16f1823 @ 32MHz  *
* 2013 Erdélyi Viktor  *
*        SLAVE        *
***********************/
// Set I2C parameters
const Slave = 0x69;                     // Set I2C device address
const Delay_Time = 250;                 // Port check delay
unsigned short j;                       // just dummy for buffer read
unsigned short rxbuffer;
unsigned short tx_data;

// 8 bit variables
typedef unsigned char uint8;
typedef unsigned int uint16;

// flags
bit oldstate;
bit echoold;

// Variables
uint8 Dist1;                             //Distance and azimuth variables
uint8 Pot1;
uint8 Pot2;
uint8 Pitch;
uint16 ADC0;
uint16 ADC1;
// denominate I/O bits

sbit Echo at RC2_bit;
sbit Echo_d at TRISC2_bit;
sbit Trig at RA2_bit;
sbit Trig_d at TRISA2_bit;
sbit LED at RC3_bit;
sbit LED_d at TRISC3_bit;

void Tone1() {
     Sound_Play(500, 20);               // Frequency = 500Hz, duration = 20ms
     //Sound_Play(Pitch, 20);           // Uncomment to modulate pitch
}

void hardinit(void) {
     ANSELA  = 0b00000011;              // Configure AN pins as digital, expect AN0 and AN1
     ANSELC = 0;
     C1ON_bit = 0;                      // Disable comparators
     C2ON_bit = 0;
     SSPCON = 0x36;                       // Set to I2C slave with 7-bit address
     PIE1.SSP1IF = 1;                      // enable SSP interrupts
     SSPADD =  Slave;
     INTCON = 0xC0;                       // enable INTCON.GIE
     APFCON = 0b10000100;
     Echo_d = 1;                        // Init I/O ports
     Trig_d = 0;
     Trig = 0;
     Sound_Init(&PORTC, 4);             // Init sound
     PWM1_Init(25000);                  // Initialize PWM1 module at 25KHz
     PWM1_Start();                      // Start PWM1
     ADC_Init();                        // ADC init
     oldstate = 0;                      // Init flags
     echoold = 0;
     Dist1 = 0;                         // Initialize variables
     Pot1 = 0;
     Pot2 = 0;
     Pitch = 400;
     LED_d = 0;
     LED = 0;
}

void interrupt(){                      // I2C slave interrupt handler
  if (PIR1.SSP1IF == 1){                // I2C Interrupt
    PIR1.SSP1IF = 0;                    // reset SSP interrupt flag
    LED=1;                                 // Just to see interrupt
    //transmit data to master
    if (SSPSTAT.b2 == 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.b5 == 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 adcread(void){                    // Reading ADC values, converting into 8 bit format
     ADC0 = ADC_Read(0);               // reading 10-bit value from ADC
     ADC1= ADC_Read(1);

     Pot1 = ADC0 >> 2;                 // writeing significant 8 bit to variable
     Pot2 = ADC1 >> 2;
}

void distM(void) {                     // Subroitune for distance measuring
     Dist1 = 255;
     echoold = 0;
     oldstate = 0;
     Trig = 1;
     oldstate = 1;
     delay_us(11);
     Trig = 0;
     if (oldstate == 1){
        while (echoold == 0){
              if (Echo == 1){
                 echoold = 1;
                 while (Echo == 1) {
                       delay_us(100);   // 17 mm precision
                       Dist1 --;
                       //Pitch = Dist2*5+400;    // +17 mm => +5 Hz (uncomment to modulate Pitch)
                       }
                 }
              }
        }
     }

void main() {
     hardinit();
     while(1) {

              if (rxbuffer == 0xFF){
                 adcread();                         // Reading ADC channels
                 distM();                           // Measuring distance
                 PWM1_Set_Duty(Dist1);              // Set volume
                 Tone1();                           // Play Tone
                 }
     }
}
The I2C lines are pulled up with 10k resistors. I have no idea...

FranzOrtiz
Posts: 1
Joined: 20 Jan 2014 22:56

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

#34 Post by FranzOrtiz » 29 Jun 2014 01:48

Hi everyone... well I do some changes for the MASTER and SLAVE codes, and it works very well in my simulations and in my PROTOBOARD. For de master I used a PIC18F4550 and for the slave I used a PIC 16F877A. I hope this can help to all of you. :)

Here is te MASTER CODE:

Code: Select all

//1.============================================================================
// PRÁCTICA:      Comunicación I2C Master_Slave.c
// AUTORES:       Francisco Ortiz O.
// FECHA:         02-Mayo-2014
// DESCRIPCIÓN:   El siguiente programa realiza la comunicación I2C entre dos
//                microcontroladores. Esta parte del código configura al micro_
//                controlador PIC18F4550 como MAESTRO, el cual se comunicará con
//                un microcontrolador PIC16F877A que se encuentra configurado
//                como ESCLAVO. Enviamos el estado de un potenciómetro conectado
//                en el canal analógico A0 del MAESTRO, y al presionar el pul_
//                sante conectado en RA1 enviado las letras "UPS" secuencialmente.
//==============================================================================
//2. ARCHIVOS DE CABECERA
//==============================================================================
// 3.===========================================================================
// DECLARACIÓN DE VARIABLES GLOBALES.
//==============================================================================
unsigned int lectura;
// 4.===========================================================================
// DECLARACIÓN DE PROTOTIPOS DE PROCEDIMIENTOS Y FUNCIONES.
//==============================================================================
void escribir_Pic(unsigned int address, 
                  unsigned int send_data);   // Escribe al ESCLAVO
unsigned short leer_Pic();                   // Lee datos del ESCLAVO
void Init_Perifericos();                     //Iniciliza el PIC
// 5.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DE LAS INTERRUPCIONES.
//==============================================================================

// 6.===========================================================================
// DEFINICIÓN DEL PROCEDIMIENTO DE ATENCIÓN A LAS INTERRUPCIONES.
//==============================================================================

// 7.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DEL PROGRAMA PRINCIPAL.
//==============================================================================
void escribir_Pic(unsigned int address, unsigned int send_data){
     I2C1_Start();            //Inicia Bus I2C
     I2C1_Wr(0xB0);           //Envía dirección del ESCLAVO (dirección + W)
     I2C1_Wr(address);        //Envía dirección de almacenamiento en el ESCLAVO
     I2C1_Wr(send_data);      //Envía el dato a escribir en el ESCLAVO
     I2C1_Stop();             //Detiene Bus I2C
     delay_ms(50);
}

unsigned short leer_Pic(){
  unsigned short read_data;
  I2C1_Start();                //Inicia Bus I2C
  I2C1_Wr(0xB1);               //Envía dirección del ESCLAVO (dirección + R)
  read_data = I2C1_Rd(0);
  delay_ms(100);
  I2C1_Stop();                 //Detiene Bus I2C
  return read_data;
}

void Init_Perifericos(){
     ADCON1 = 0x0E;             // RA0 como entrada analógica, RA1-RA6 Digitales
     CMCON = 0b00000111;        // Deshabilita comparadores
     INTCON2 = 0x80;            // Deshabilita pull up en el puerto B

     // clears internal latches
     LATA = 0xFF;
     LATC = 0x00;
     LATD = 0x00;
     LATE = 0x00;

     TRISA = 0xFF;
     TRISB = 0x00;
     TRISC = 0x00;
     TRISD = 0x00;
     TRISE = 0x00;
}
// 8.===========================================================================
// DEFINICIÓN DEL PROGRAMA PRINCIPAL.
//==============================================================================
void main(){
   bit oldstate,oldstate1;
   Init_Perifericos();
   ADC_Init();
   I2C1_Init(100000);       //Inicializar Bus I2C a 100kHz
   delay_ms(500);
   while (1){
         lectura = ADC_Read(0)/4;       //Obtener una lectura de 8bits
         escribir_Pic(4,lectura);       //Escribimos al ESCLAVO
         if (Button(&PORTA, 1, 1, 1)) {               // Detect logical one
            oldstate = 1;                             // Update flag
         }
         if (oldstate && Button(&PORTA, 1, 1, 0)) { // Detect one-to-zero transition
            escribir_Pic(1,0x55);     //Escribimos una "U" al esclavo
            delay_ms(20);
            escribir_Pic(2,0x50);     //Escribimos una "P" al esclavo
            delay_ms(20);
            escribir_Pic(3,0x53);     //Escribimos una "S" al esclavo
            oldstate = 0;                              // Update flag
         }
   }
}
And here is the SLAVE CODE:

Code: Select all

//1.============================================================================
// PRÁCTICA:      Comunicación I2C Master_Slave.c
// AUTORES:       Francisco Ortiz O.
// FECHA:         02-Mayo-2014
// DESCRIPCIÓN:   Este código se encarga de configurar al
//                microcontrolador PIC16F877A como esclavo para que atienda las
//                interrupciones generadas por el maestro; que es un microcon_
//                trolador PIC18F4550 y atiende solo a la dirección 0xB0.
//                Realizamos la lectura del estado de un potenciómetro conectado
//                en el maestro y mostramos los datos en un LCD 2x16.
//==============================================================================
//2. ARCHIVOS DE CABECERA
//==============================================================================
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// 3.===========================================================================
// DECLARACIÓN DE VARIABLES GLOBALES.
//==============================================================================
unsigned char rxbuffer,address,buff,dato, direccion;
unsigned short tx_data;
int a=0;
// 4.===========================================================================
// DECLARACIÓN DE PROTOTIPOS DE PROCEDIMIENTOS Y FUNCIONES.
//==============================================================================
void initPerifericos();
unsigned short BcdToShort( unsigned short bcd );
unsigned short ShortToBcd( unsigned short valor);
// 5.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DE LAS INTERRUPCIONES.
//==============================================================================

// 6.===========================================================================
// DEFINICIÓN DEL PROCEDIMIENTO DE ATENCIÓN A LAS INTERRUPCIONES.
//==============================================================================
void interrupt(){
     if (PIR1.SSPIF){                  //Comprueba si la interrupción es por I2C
        PIR1.SSPIF = 0;                //Apagamos la bandera SSP
        if(!SSPSTAT.R_W & SSPSTAT.D_A & SSPSTAT.BF ){
            a++;
            PORTB=2;
            if (a==1){
               address=SSPBUF;        //Guardamos la dirección de almacenamiento
            }                         //del dato recibido.
            if (a==2){
               rxbuffer=SSPBUF;       //Guardamos el dato recibido
               a=0;
            }
            PIR1.SSPIF = 0;           //Apagamos la bandera SSP
        }
            
        if( !SSPSTAT.R_W & !SSPSTAT.D_A & SSPSTAT.BF ){
            buff = SSPBUF;
            PIR1.SSPIF = 0;
        }
     }
}
// 7.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DEL PROGRAMA PRINCIPAL.
//==============================================================================
void initPerifericos(){
     ADCON1 = 7;                     // Todos los puertos como digitales
     CMCON = 0b00000111;             // Deshabilita comparadores
     TRISA = 0;                      // Set PORTA as output
     TRISB = 0;                      // Set PORTB as output
     //TRISC = 0b00011000;             // Set SCL y SDA como ingresos
     TRISC.B3 = 1; // Set SCL (PORTC,3) pin como ingreso
     TRISC.B4 = 1; // Set SDA (PORTC,4) pin como ingreso
     PortB=0;
     
     //Configuracion de interrupciones
     INTCON = 0b00000000;
     SSPCON = 0b00111110;         // Modo esclavo 7 bits de direccion.
     SSPCON2 = 0x00;
     SSPADD = 0xB0;               //Dirección del dispositivo
     SSPSTAT=0x00;
     SSPCON.SSPEN = 1;
     SSPSTAT.SMP = 1;
     SSPSTAT.CKE = 1;
     PIR1.SSPIF = 0;
     PIR2.BCLIF=0;

     PIE1.SSPIE = 1;         // Habilita la interrupcion del modulo SSP
     INTCON.PEIE = 1;        // Habilita las interrupciones de los perifericos
     INTCON.GIE = 1;         // Habilita las interrupciones globales!
}

unsigned short BcdToShort( unsigned short bcd ){
     unsigned short LV, HV;
     LV = bcd&0x0F;
     HV = (bcd>>4)&0x0F;
     return LV + HV*10;
}
unsigned short ShortToBcd( unsigned short valor){
     unsigned short HV, LV;
     HV = valor/10;
     LV = valor - HV*10;
     return LV + HV*16;
}
// 8.===========================================================================
// DEFINICIÓN DEL PROGRAMA PRINCIPAL.
//==============================================================================
void main(){
     char as[6];
     initPerifericos();
     Lcd_Init();               // Initialize LCD
     Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
     Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off
     lcd_Out(1,1,"SLAVE");
     while (1){
           if (address==4){            //Si la dirección es 4 es dato del pot.
              intToStr(rxbuffer,as);
              lcd_out(1,10,as);
              delay_ms(50);

           }
           if (address!= 4){           //Si es diferente de 4 mostrar datos en
              dato=rxbuffer;           //el LCD.
              direccion=address;
              lcd_chr(2,direccion,dato);
           }
     }
}
Here is the link for the simulations and codes. :wink: :D
https://www.dropbox.com/s/if8kfvh84wgoe ... 0Slave.rar

congduc1352
Posts: 3
Joined: 09 Jun 2014 09:19

Re:Plz show me the false.!!!

#35 Post by congduc1352 » 05 Jul 2014 09:30

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


Remo
Plz show me the false.
thanks!

congduc1352
Posts: 3
Joined: 09 Jun 2014 09:19

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

#36 Post by congduc1352 » 08 Jul 2014 19:02

Hey guys! This my I2C project, it's working very well.
My project have 1 Master and 2 slave, you can add more slave if you want.

Key A, B chose slave which you wanna send data before send something.

:arrow:
1 I2C.zip
(182.8 KiB) Downloaded 870 times
To TomSS and FranzOrtiz my thankful!
.
.

jayanthd
Posts: 630
Joined: 08 May 2013 18:31
Location: Bangalore

Re: It works now!!!

#37 Post by jayanthd » 27 May 2015 11:28

@TomSSS

I have a similar problem. My slave is not sending data to master. When master requests data slave has to send 4 bytes. Please help me with the code.
Attachments
I2C Master Slave rev2.rar
(234.79 KiB) Downloaded 358 times
[HW:] EasyPIC v7, mikroProg PIC, AVR, STM32, PSoC, Tiva, 8051
[SW:] mikroC PRO PIC, dsPIC, PIC32, AVR, ARM, 8051
mikroBasic PRO PIC, dsPIC, PIC32, AVR, ARM, 8051
mikroPascal PRO PIC, dsPIC, PIC32, AVR, ARM, 8051
Visual GLCD, Visual TFT

Ntokozo
Posts: 1
Joined: 01 Sep 2015 16:56

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

#38 Post by Ntokozo » 01 Sep 2015 17:13

Hellow

I am new here. Im trying to use two PIC18F13K50 as master-slave I2C communication and I have used the example code that i found here but its not working. Anyone who can help me please help.

Thanks in advance
Ntokozo

Jhrick
Posts: 3
Joined: 09 Sep 2015 14:58

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

#39 Post by Jhrick » 09 Sep 2015 15:05

Please, I need to convert this program to MikroBasic Pro for Pic. The design features are the same, I just need to do the conversion, but I'm having some difficulties and would like someone to help me in this.
Thank you

Bugz Bensce
Posts: 11
Joined: 09 Nov 2015 20:29

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

#40 Post by Bugz Bensce » 10 Nov 2015 07:05

I did the Code in Hi-tech C (MPLAB X) and it's working perfectly.
The Master continuously sends a code to the slave which is output via a 7- segment display at Port D.
In addition, the Master can read Data from the slave via a button press and Display the Read via a 7-segment display of it's own
on Port D.
I used User defined Libraries for everything, that includes i2c and delays. If you want the full Code(Master/ slave and Proteus simulation) you can find it below in a Zipped folder.
Attachments
PIC-to-PIC I2C.jpg
PIC-to-PIC I2C.jpg (137.57 KiB) Viewed 11073 times
i2c_Master_slave.zip
(212.66 KiB) Downloaded 293 times

Bugz Bensce
Posts: 11
Joined: 09 Nov 2015 20:29

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

#41 Post by Bugz Bensce » 10 Nov 2015 16:01

Greetings,
I have successfully done PIC-to-PIC I2C communication.
The system has a Master and Slave. The Master continuously sends (Writes) a Binary code to be displayed by the Slave (Via Port D).
In addition the Master can request a Read from the Slave via a Button press and display that data via Port D too.
I have included the code for both Master and Slave, and the Proteus simulation in a Zip folder below.
The code is written in Hi-Tech C compiler (MPlab X). It's fully commented and intuitive but if you have any queries please feel free to ask. :wink:
Attachments
i2c_Master_slave.zip
All code is user defined, that is - I2C, and even delays.
(212.66 KiB) Downloaded 402 times

ventete
Posts: 20
Joined: 26 Mar 2011 21:09

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

#42 Post by ventete » 17 Nov 2015 00:14

Hi Tom,
I have a silly question: if the slave is using portC for inputs to send data back to the master, how do you connect the master to the slave since the I2C link is already using two of the portC pins (14 and 15 on the PIC16F876A) thank you, Marc

Post Reply

Return to “mikroC General”