• Domingo 28 de Abril de 2024, 21:21

Autor Tema:  Comunicacion i2c MULTI_MASTER entre PICs  (Leído 6058 veces)

mizzard

  • Nuevo Miembro
  • *
  • Mensajes: 22
    • Ver Perfil
Comunicacion i2c MULTI_MASTER entre PICs
« en: Jueves 13 de Enero de 2011, 15:05 »
0
Hola a todos, antes de nada os comentaré la situación.

Estamos desarrollando un proyecto en el cual se van a comunicar diferentes PICs por un bus único, escogiendo como lenguaje el I2C y el compilador CCS.
La idea es que habrá un PIC que actuará de Maestro y gestionará la recopilación de datos de los otros microcontroladores. A este PIC lo llamaremos CEREBRO y será un PIC18F2550.

Así, que de forma ideal tendríamos un árbol en el que arriba del todo estaría CEREBRO y en las ramificaciones los diferentes PICs esclavos. Es por ello que toda comunicación debe pasar por CEREBRO.

Pues bien, existen una serie de microcontroladores que no pueden actuar como esclavos y únicamente pueden ser maestros, como el caso del módulo GSM y posiblemente WIFI (aún no se ha escogido el módulo definitivo y ambos no son de MICROCHIP).

El primer problema que se presenta es que se rompe con la filosofia que habia planteado, por lo que necesitaria implementar la función MULTI_MASTER en la cual en determinadas situaciones un PIC puede ser MAESTRO y en otras ESCLAVO.

Después de realizar numerosas pruebas simplificando el problema y comprobando que todas son exitosas (Comunicación entre un maestro y un esclavo; un maestro y dos esclavos) tanto en la lectura como en la escritura en un esclavo. Se ha procedido a la simplificación del problema.


-   Para el primer caso se ha realizado la siguiente configuración:


GSM (MASTER) -> PIC ATMEL ARQUITECTURA ARM (identificador 0x51)
CEREBRO (MULTI_MASTER)-> PIC18f2550 (direccion esclava 0x20)

implementando la función:
#use i2c(MULTI_MASTER, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2C)

Lo único que se ha hecho es que cuando se inicializa GSM, éste comunica por I2C a cerebro que ha arrancado, enviando en HEX (0x20 0x51 0xEE 0x0D 0x0A). Pues cuando implemento en el use i2c el modo MULTI_MASTER, cerebro no responde (si se configura como esclavo y omitiendo las funciones   void i2c_init(void);   int8 i2c_mm_start(int8);   void i2c_mm_stop(void); si que funciona)

Para ello nos hemos apoyado del siguiente enlace implementando las funciones citadas.
h t t p : // w w w . c c s i n f o . c o m / f o r u m / v i e w t o p i c . p h p ? t = 4 2 6 2 6 & h i g h l i g h t = m u l t i m a s t e r
(Solucion propuesta por Wayne_)


/////////////////////////////////////////////////////////////////////////
MAIN.H
/////////////////////////////////////////////////////////////////////////


#include <18F2550.h>

#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HSPLL                    //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT               //No brownout reset
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOMCLR                   //No Master Clear pin enabled
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL5                     //Divide By 12(48MHz oscillator input)
#FUSES CPUDIV1                  //System Clock by 4

//Configuracion de los registros
#BYTE SSPADD = 0xFC8
#BYTE SSPCON1 = 0xFC6
#BYTE SSPCON2 = 0xFC5

// Desactivamos el USB para poder usar los pines C4 y C5 como entradas digitales
#FUSES NOUSBDIV
#FUSES NOVREGEN
#BYTE UCON = 0xF6D
#BYTE UCFG = 0xF6F  
#use delay(clock=48000000)

//==============================================================================
//-----------------------  DEFINICIONES  ---------------------------------------
//==============================================================================

#define enciende  OUTPUT_HIGH
#define apaga     OUTPUT_LOW

#define PWR_IND   PIN_B2
#define I2C_PIC   PIN_B3
#define IGT_PIC   PIN_B4
#define EMOFF_PIC PIN_B5


#define puls1 input(PIN_C4)
#define puls2 input(PIN_C5)
#define puls3 input(PIN_C6)

#define ledVerde     PIN_C2
#define ledAmarillo  PIN_C1
#define ledRojo      PIN_C0

#define tamBuff 122
#define moverMotores PIN_A0
#define _timeout 60000

////////////////////////////////////////////////////////////////////////
MAIN.C
////////////////////////////////////////////////////////////////////////


#include <main.h>
#include <string.h>
#include "flex_lcd.c"
#use i2c(MULTI_MASTER ,address=0x20, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2C)
#use rs232(baud=115200,parity=N,xmit=PIN_B7,rcv=PIN_B6,bits=8,stream = canal_debug)    

//==============================================================================
//-----------------------  DECLARACIÓN VARIABLES GLOBALES  ---------------------
//==============================================================================
   BYTE baud_rate;
   BYTE bufferRx[tamBuff], bufferTx[tamBuff];
   
   int i=0;
   int estado=0;
   BYTE incoming, state, comando;
   int1 banderaTramaGSM, banderaMano, banderaGSMOK;
   
//==============================================================================
//-----------------------  DECLARACIÓN DE FUNCIONES  ---------------------------
//==============================================================================

   void inicializaPIC(void);
   void inicializaGSM(void);
   void lecturaGSM(void);
   void estadoDeVuelta(void);
   void i2c_init(void);
   int8 i2c_mm_start(int8);
   void i2c_mm_stop(void);

//==============================================================================
//-----------------------  INTERRUPCIONES --------------------------------------
//==============================================================================

#int_SSP // interrupt on i2c activity
void  i2c_isr(void)
{

   state = i2c_isr_state();
   //Si estoy en recepcion
   if(state < 0x80){                     // Un maestro nos envia datos (algun modulo)
      //Entonces leo el bus
      incoming = i2c_read(I2C);
                 
      // Primer byte es identificador de modulo que comunica          
      if(state == 1){                    
         switch(incoming){

            case 0x51:
               banderaTramaGSM = 1;              
               break;
            case 0x52:
               banderaMano = 1;      
               break;
            default:              
               break;
         }
      }
      // Resto de los bytes son datos
      if(state == 2){                                
         comando = incoming;              
      }
      if(state > 2){
         bufferRx[state-3] = incoming;
     
      }
   }else if(state >= 0x80){                     //Master is requesting data
   
      i2c_write(bufferTx[tamBuff]);
   }
}

//==============================================================================
//-----------------------     FUNCIONES      -----------------------------------
//==============================================================================

void i2c_init() {
   baud_rate = SSPADD;
   SSPCON1 = (SSPCON1 & 0xF0) | 0x06;   // Slave mode
   SSPCON2 |= 0x01;   // Slave mode clock stretching NO MACHACA INFO
   SSPADD = 0x20;
   delay_ms(25);
   fprintf(canal_debug,"SSPADD: %u  n",SSPADD);
   enable_interrupts(INT_BUSCOL);
   enable_interrupts(INT_SSP);
}
//==============================================================================

// I2C multiMaster start
int8 i2c_mm_start(int8 address)
{
   int8 ack;
   
   disable_interrupts(INT_SSP);
   SSPCON2 &= ~0x01;
   SSPCON1 = (SSPCON1 & 0xF0) | 0x08;   // Master mode
   SSPADD = baud_rate;
   do {
      i2c_start(I2C, 1);
      ack = i2c_write(address);   // Send address with WE (returns 0 = ACK, 1 = NOACK, 2 = Collision)
   } while (ack == 2);   // Bus Collision
   return(ack);
}

//==============================================================================

// I2C multiMaster stop
void i2c_mm_stop()
{
   i2c_stop();
   while (SSPADD != baud_rate) {}
   SSPCON1 = (SSPCON1 & 0xF0) | 0x06;   // Slave mode
   SSPCON2 |= 0x01;   // Slave mode clock stretching
   SSPADD = 0x20;   // Slave mode
   clear_interrupt(INT_SSP);
   enable_interrupts(INT_SSP);
}


//==============================================================================
//==============================================================================


void inicializaPIC(void){

   //Configuracion Timer's
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);

   setup_wdt(WDT_OFF);


   //Configuracion I2C
   //enable_interrupts(INT_SSP);
   i2c_init();
   //i2c_mm_start(0x10);
  // i2c_mm_stop();
   
   //Configuracion Interrupciones
  enable_interrupts(GLOBAL);

   for(i=0;i<tamBuff;i++){
      bufferRx=0;
      bufferTx=0;
   }
   incoming=0;

   banderaTramaGSM = 0;
//   banderaMano = 0;
   banderaGSMOK = 0;
   comando = 0;


   apaga(ledVerde);
   apaga(ledAmarillo);
   apaga(ledRojo);

   estado++;
   
   return;
   
}

//==============================================================================

void inicializaGSM(void){
// Esta parte de código no interesa porque no afecta a la comunicacion
}

//==============================================================================
void lecturaGSM(void){

   int len = 0;

// Esperamos a recibir el fin de trama 0x0D 0x0A

   if (banderaTramaGSM == 1){        
     
         if(state > 3 && bufferRx[state-4]==0x0D && bufferRx[state-3]==0x0A){

            switch(comando){
               
               case 0xAA:      

                  lcd_putc("f");
                  len = strlen(bufferRx);
               
                  // Envio el mensaje recibido al PC
                  fprintf(canal_debug,"El mensaje es: %s",bufferRx);
               
                  /*
                  i2c_start(I2CM);
                  i2c_write(I2CM,0x10);      //i2c address of a slave device
                  i2c_write(I2CM,0x51);      //1st byte to slave
                  i2c_write(I2CM,0xaa);      //2nd byte to slave
                  i2c_write(I2CM,0x11);      //2nd byte to slave
                  i2c_write(I2CM,0x22);      //2nd byte to slave
                  i2c_write(I2CM,0x33);      //2nd byte to slave
                  i2c_write(I2CM,0x44);      //2nd byte to slave
                  i2c_write(I2CM,0x0D);      //2nd byte to slave
                  i2c_write(I2CM,0x0a);      //2nd byte to slave
                  i2c_stop(I2CM);
                  */
                  fprintf(canal_debug,"Mensaje enviado correctamenten");              
                  break;

      // Esto es lo que se debería mostrar si la comunicacion es exitosa
               case 0xEE:
             
                  banderaGSMOK = 1;
                  fprintf(canal_debug,"GSM conectadon");
                  lcd_putc("fSystem OK");                                  
                  enciende(ledVerde);
               
                  break;

               default:
                  fprintf(canal_debug,"Instruccion de GSM no reconocidan");
                  break;
           
            }
            //Limpio el buffer del i2c
            for(i=0;i<tamBuff;i++){
               bufferRx=0;
            }
            banderaTramaGSM = 0;
           
         }
   }else{
      estado++;
   }
}

//==============================================================================

void estadoDeVuelta(void){

   estado = 3;
   return;

}
//==============================================================================
//----------------------- PROGRAMA PRINCIPAL -----------------------------------
//==============================================================================

void main()
{
   estado = 0;

   while(TRUE){
   
      switch (estado){
   
         case 0:
            inicializaPIC();
            break;
         case 1:
            lcd_init();
            lcd_putc("fLoading System...");            
            fprintf(canal_debug,"Inicializacion LCD: OK n");
            estado++;
            break;            
         case 2:
            inicializaGSM();    
            break;
         case 3:  
            lecturaGSM();
            break;
         case 4:
            estadoDeVuelta();
            break;    
         default:
            reset_cpu();
            break;
      }
   }
}
////////////////////////////////////////////////////////////////////////

Se trata de una simple prueba para ver si dentro del modo MULTI_MASTER, cerebro puede actuar de esclavo, respondiendo a GSM.

Para este caso no se si estoy accediendo bien a los registros, si estoy haciendo bien lo que comenta Wayne_ en el foro de CCS o qué es lo que está pasando, porque no es capaz de responder.



-   Para el segundo caso se ha realizado la siguiente configuración:

CEREBRO (MULTI_MASTER) -> PIC18F2550 (identificador 0x20)
MANO (SLAVE)-> PIC16F690 (direccion esclavo 0x10)
 
Desde cerebro se disponen 2 botones uno para realizar una petición de escritura y el otro para hacer una lectura a mano. Para ello jugamos con la configuración del use i2c para cambiar el comportamiento del micro. Realizando numerosas pruebas, parece que únicamente hace caso del primer use i2c que se introduce ignorando el posterior.

/////////////////////////////////////////
CEREBRO
MAIN .C (MAIN.H ES EL MISMO QUE ANTES)
/////////////////////////////////////////


#include <main.h>
#include <string.h>
#include "flex_lcd.c"
 
//#use i2c(MASTER, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2CM)
#use i2c(SLAVE,address=0x20, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2CS)

#use rs232(baud=115200,parity=N,xmit=PIN_B7,rcv=PIN_B6,bits=8, stream = canal_debug)    

//==============================================================================
//-----------------------  DECLARACIÓN VARIABLES GLOBALES  ---------------------
//==============================================================================
 
   BYTE bufferRx[tamBuff], bufferTx[tamBuff];
   BYTE incoming, state, comando;
   
   int1 banderaTramaGSM, banderaMano, banderaGSMOK;
   
   int i=0;
   int estado=0;

//==============================================================================
//-----------------------  DECLARACIÓN DE FUNCIONES  ---------------------------
//==============================================================================

   void inicializaPIC(void);
   void inicializaGSM(void);
   void lecturaI2C(void);
   void estadoDeVuelta(void);
   void puls(void);


//==============================================================================
//-----------------------  INTERRUPCIONES --------------------------------------
//==============================================================================

#int_SSP // interrupt on i2c activity
void  i2c_isr(void)
{

   state = i2c_isr_state(I2CS);

   //Si estoy en recepcion
   if(state < 0x80){                     // Un maestro nos envia datos (algun modulo)
   
      //Entonces leo el bus
      incoming = i2c_read(I2CS);
                 
      // Primer byte es identificador de modulo que comunica          
      if(state == 1){                    

         switch(incoming){

            case 0x51:
               banderaTramaGSM = 1;              
               break;
            case 0x52:
               banderaMano = 1;      
               break;
            default:              
               break;
         }
      }
      // Resto de los bytes son datos
      if(state == 2){                                
         comando = incoming;              
      }
      if(state > 2){
         bufferRx[state-3] = incoming;
     
      }
   }else if(state >= 0x80){                     //Master is requesting data
   
      i2c_write(I2CS,bufferTx[tamBuff]);
   }
}


//==============================================================================
//-----------------------     FUNCIONES      -----------------------------------
//==============================================================================

void inicializaPIC(void){

   //Configuracion Timer's
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   setup_wdt(WDT_OFF);

   //Configuracion I2C

 
   enable_interrupts(INT_BUSCOL);
   enable_interrupts(INT_SSP);

   //Configuracion Interrupciones
   bit_clear(UCON,3);
   bit_set(UCFG,3);    
   enable_interrupts(GLOBAL);

   banderaGSMOK = 0;

   apaga(ledVerde);
   apaga(ledAmarillo);
   apaga(ledRojo);

   estado++;
   
   return;
   
}

//==============================================================================
void inicializaGSM(void){
// CÓDIGO QUE NO INTERESA YA QUE NO INTERVIENE EN LA COMUNICACION
}

//==============================================================================
//==============================================================================

void lecturaI2C(void){

   if (banderaTramaCerebro == 1){        
     
         if(state > 3 && bufferRx[state-4]==0x0D && bufferRx[state-3]==0x0A){

            switch(comando){
               
               case 0xAA:      
                  // Envio el mensaje recibido al PC
                  fprintf(canal_debug,"TIPO DATO 1 es: %s",bufferRx);
                  break;
                                         
               case 0xBB:
                  // Envio el numero recibido al PC              
                  fprintf(canal_debug,"TIPO DATO 2 es: %s",bufferRx);
                   break;

               case 0xCC:
                  // Envio el numero recibido al PC
                  fprintf(canal_debug,"TIPO DATO 3 es: %s",bufferRx);;
                  break;
               default:
                  fprintf(canal_debug,"Instruccion de GSM no reconocidan");
                  break;
            }
            //Limpio el buffer del i2c
            for(i=0;i<tamBuff;i++){
               bufferRx=0;
            }
            banderaTramaCerebro = 0;
         }
   }
 
  if (banderaTramaGSM == 1){        
         if(state > 3 && bufferRx[state-4]==0x0D && bufferRx[state-3]==0x0A){
            switch(comando){
               
               case 0xAA:      
                  // Envio el mensaje recibido al PC
                  fprintf(canal_debug,"TIPO DATO 1 es: %s",bufferRx);
                  break;
                                         
               case 0xBB:
                  // Envio el numero recibido al PC              
                  fprintf(canal_debug,"TIPO DATO 2 es: %s",bufferRx);
                   break;

               case 0xCC:
                  // Envio el numero recibido al PC
                  fprintf(canal_debug,"TIPO DATO 3 es: %s",bufferRx);
                  break;                
               default:  
                  fprintf(canal_debug,"Instruccion de GSM no reconocidan");
                  break;
            }
            //Limpio el buffer del i2c
            for(i=0;i<tamBuff;i++){
               bufferRx=0;
            }
            banderaTramaGSM = 0;
         }
   }else{
      estado++;
   }
}


//==============================================================================
void puls(void){

   int ack;
   byte datoEscribirEsclavo[4]={0x11 0x22 0x33 0x44};
   byte datoLeerEsclavo[4];
   int n=0;
   int i=0;

////////////////////////////////////////////////////////////////////////////////
//                   ESCRIBIMOS EN ESCLAVO
////////////////////////////////////////////////////////////////////////////////

   if(!puls1){
   #use i2c(MASTER, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2CM)
      enciende(ledRojo);
      disable_interrupts(GLOBAL);
      disable_interrupts(INT_SSP);
      enable_interrupts(GLOBAL);
     do {
         i2c_start(I2CM, 1);
         ack = i2c_write(I2CM,0x10);   // Send address with WE (returns 0 = ACK, 1 = NOACK, 2 = Collision)
      } while (ack == 2);   // Bus Collision
     
      fprintf(canal_debug,"Inicio trama i2cn");
      i2c_write(I2CM,0x20);  // Indico que soy cerebro  
      i2c_write(I2CM,0xaa);  // Tipo de datos

      for(n=0;n<4;n++){
         i2c_write(I2CM,datoEscribirEsclavo[n]);   // Bucle para enviar cadena de información
      }

      i2c_write(I2CM,0x0D);  // Final de trama 1
      i2c_write(I2CM,0x0A);  // Final de trama 2    
      i2c_stop(I2CM);       // Condicion de parada
      fprintf(canal_debug,"Fin trama i2cn");
      delay_ms(500);
   }
   
////////////////////////////////////////////////////////////////////////////////
//       LEEMOS DEL ESCLAVO (NO HACE FALTA ACTIVAR INTERRUPCION I2C)
////////////////////////////////////////////////////////////////////////////////

   else if(!puls2){ // Leemos de esclavo
   #use i2c(MASTER, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2CM)
      enciende(ledAmarillo);
      disable_interrupts(GLOBAL);
      disable_interrupts(INT_SSP);
      enable_interrupts(GLOBAL);
      do {
         i2c_start(I2CM, 1);
         ack = i2c_write(I2CM,0x10+1);   // Send address with WE (returns 0 = ACK, 1 = NOACK, 2 = Collision)
      } while (ack == 2);   // Bus Collision
     
      for(i=0;i<3;i++){
         datoLeerEsclavo=i2c_read(I2CM,1);
      }
     
      datoLeerEsclavo=i2c_read(I2CM,0);  // Ponemos el 0 indicando ultimo byte a leer
      i2c_stop(I2CM);       // Condicion de parada
      fprintf(canal_debug,"Fin trama i2cn");
      delay_ms(500);
     
      for(i=0;i<=3;i++){
         fprintf(canal_debug,"nTrama recibida %i: %x",i,datoLeerEsclavo);  //Mostramos la info
      }
     
   }else{
      apaga(ledRojo);
      apaga(ledAmarillo);
      #use i2c(SLAVE,address=0x20, sda=PIN_B0, scl=PIN_B1,SLOW, force_hw, stream=I2CS)
      disable_interrupts(GLOBAL);
      enable_interrupts(INT_SSP);
      enable_interrupts(GLOBAL);
      estado++;
   }
   return;
}

//==============================================================================
void estadoDeVuelta(void){

   estado = 3;
   return;
}

//==============================================================================
//----------------------- PROGRAMA PRINCIPAL -----------------------------------
//==============================================================================

void main()
{
   estado = 0;

   while(TRUE){
   
      switch (estado){
   
         case 0:
            inicializaPIC();
            break;
         case 1:
            lcd_init();
            lcd_putc("fSystem LOADED");            
            estado++;
            break;
         case 2:
            inicializaGSM();    
            break;
         case 3:
            lecturaI2C();    
            break;            
         case 4:
            puls();  
            break;
         case 5:
            estadoDeVuelta();
            break;    
         default:
            reset_cpu();
            break;
      }
   }
}

/////////////////////////////////////////
MANO
MAIN .H
/////////////////////////////////////////


#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //No brownout reset
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES PUT                      //Power Up Timer
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled

#use delay(clock=20000000)

//----------------------- DEFINICIONES -----------------------------------------

#define tamBuff 60



/////////////////////////////////////////
MANO
MAIN .C
/////////////////////////////////////////


#include <16F690.h>
#include <main.h>

#use i2c(SLAVE, sda=PIN_B4, scl=PIN_B6, address=0x10, SLOW, force_hw, stream=I2CS)
#use rs232(baud=115200,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8,stream = canal_debug)

//==============================================================================
//-----------------------  DECLARACIÓN VARIABLES GLOBALES  ---------------------
//==============================================================================
   
   int i=0;
   int estado=0;

   BYTE state, incoming;
   BYTE bufferRx[tamBuff], bufferTx[tamBuff];

   int1 banderaTramaCerebro,banderaTramaGSM;
   BYTE comando;
   byte dato[4]={0x99 0x88 0x77 0x66};

//==============================================================================
//-----------------------  DECLARACIÓN DE FUNCIONES  ---------------------------
//==============================================================================

   void inicializaPIC(void);
   void lecturaI2C(void);

//==============================================================================
//-----------------------  INTERRUPCIONES --------------------------------------
//==============================================================================


#int_SSP // interrupt on i2c activity
void  i2c_isr(void)
{
   state = i2c_isr_state();
   
   //MODO RECEPCION
   if(state < 0x80)                     // Maestro nos envia datos
   {
      incoming = i2c_read();
      //Quien me comunica
      if(state == 1){
     
         switch(incoming){

            case 0x20:
               banderaTramaCerebro= 1;
               break;
            case 0x51:
               banderaTramaGSM = 1;    
               break;              
            default:
               fprintf(canal_debug,"No conozco quien me intenta comunicar por i2cn");            
               break;
         }
     
      //Que comando me envian
      }else if(state == 2){                      // Resto de los bytes son datos
         comando = incoming;
      }else if(state > 2){
         bufferRx[state-3] = incoming;

      }
   }
   else if(state >= 0x80)                     //Master is requesting data
   {
      i2c_write(dato[state-0x80]); // De esta forma enviamos
   }
}

//==============================================================================
//-----------------------     FUNCIONES      -----------------------------------
//==============================================================================

void inicializaPIC(void){
     
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   
   for(i=0;i<tamBuff;i++){
      bufferRx=0;
      bufferTx=0;
   }

   banderaTramaCerebro=0;
   banderaTramaGSM=0;
   comando=0;
 
   fprintf(canal_debug,"ARRANQUE OK");
 
   estado++;

   return;
}

//==============================================================================
//==============================================================================

void lecturaI2C(void){

   if (banderaTramaCerebro == 1){        
     
         if(state > 3 && bufferRx[state-4]==0x0D && bufferRx[state-3]==0x0A){

            switch(comando){
               
               case 0xAA:      
                  // Envio el mensaje recibido al PC
                  fprintf(canal_debug,"TIPO DATO 1 es: %s",bufferRx);
                  break;
                                         
               case 0xBB:
                  // Envio el numero recibido al PC              
                  fprintf(canal_debug,"TIPO DATO 2 es: %s",bufferRx);
                   break;

               case 0xCC:
                  // Envio el numero recibido al PC
                  fprintf(canal_debug,"TIPO DATO 3 es: %s",bufferRx);;
                  break;
               default:
                  fprintf(canal_debug,"Instruccion de GSM no reconocidan");
                  break;
            }
            //Limpio el buffer del i2c
            for(i=0;i<tamBuff;i++){
               bufferRx=0;
            }
            banderaTramaCerebro = 0;
         }
   }
 
  if (banderaTramaGSM == 1){        
         if(state > 3 && bufferRx[state-4]==0x0D && bufferRx[state-3]==0x0A){
            switch(comando){
               
               case 0xAA:      
                  // Envio el mensaje recibido al PC
                  fprintf(canal_debug,"TIPO DATO 1 es: %s",bufferRx);
                  break;
                                         
               case 0xBB:
                  // Envio el numero recibido al PC              
                  fprintf(canal_debug,"TIPO DATO 2 es: %s",bufferRx);
                   break;

               case 0xCC:
                  // Envio el numero recibido al PC
                  fprintf(canal_debug,"TIPO DATO 3 es: %s",bufferRx);
                  break;                
               default:  
                  fprintf(canal_debug,"Instruccion de GSM no reconocidan");
                  break;
            }
            //Limpio el buffer del i2c
            for(i=0;i<tamBuff;i++){
               bufferRx=0;
            }
            banderaTramaGSM = 0;
         }
   }else{
      estado++;
   }
}

//==============================================================================
//==============================================================================

void estadoDeVuelta(void){

   estado = 1;
   return;
}


//==============================================================================
//----------------------- PROGRAMA PRINCIPAL -----------------------------------
//==============================================================================

void main()
{
   estado=0;
   
   while(TRUE){
     switch (estado){
         case 0:
            inicializaPIC();
            break;  
         case 1:
            lecturaI2C();
            break;
         case 2:
            estadoDeVuelta();
            break;            
         default:
            reset_cpu();
            break;
      }
   }
}


Si configuro CEREBRO como MASTER y quito en las partes del código los use i2c… funciona perfectamente (sin tocar el codigo de MANO), por lo que me da a pensar que el compilador no introduce los valores correctos en los registros cuando pongo los use i2c…

RESUMEN:
Alguno de vosotros ha trabajado con el modo MULTI_MASTER? (El objetivo es comunicar 2 PICs en modo MULTI_MASTER haciendo escrituras y peticiones de lecturas a ambos, cosa que no he llegado a hacer porque prefiero ir poco a poco y partiendo de cosas que funcionan)
Alguna idea de cómo podría manipular los registros?
#BYTE SSPADD = 0xFC8
#BYTE SSPCON1 = 0xFC6
#BYTE SSPCON2 = 0xFC5

me falta alguno más para hacerlo implementando funciones?

He intentado exponer mi problema lo más claro posible, cualquier duda estaré encantado de responderla, asi como agradecer cualquier sugerencia.

Muchisimas gracias y feliz año nuevo!