Dos PIC 18f4620, uno como maestro y el segundo es un problema de comunicación I2C esclavo

1

Enlace para microcontrolador PIC 18F4620 ficha técnica si puede lo necesita

Uso "Mikroc for PIC pro 6.0" como compilador y escribo un programa para comunicarme entre dos 18f4620 uno es maestro y el otro es esclavo. Tanto el esclavo como el maestro están trabajando en el oscilador HS modo con 4MHZ oscilador de cristal

El código completo para master pic 18f4620

        //MAster pic 18f4620

   const unsigned short int crystalOscillator =4000000;



    void I2C_Master_Init(const unsigned long c)
    {
     SSPCON1 = 0b00101000;
     SSPCON2 = 0;
     SSPADD = (crystalOscillator/(4*c))-1;
     SSPSTAT = 0;
     TRISC.B3 = 1; //Setting as input as given in datasheet
     TRISC.B4 = 1; //Setting as input as given in datasheet
    }



    void I2C_Master_Wait()
    {
     while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
    }



    void I2C_Master_Start()
    {
     I2C_Master_Wait();
     SSPCON2.SEN = 1;
    }



    void I2C_Master_RepeatedStart()
    {
     I2C_Master_Wait();
     SSPCON2.RSEN = 1;
    }



    void I2C_Master_Stop()
    {
     I2C_Master_Wait();
     SSPCON2.PEN = 1;
    }



    void I2C_Master_Write(unsigned short int d)
    {
     I2C_Master_Wait();
     SSPBUF = d;
    }



    unsigned short int I2C_Master_Read(unsigned short int a)
    {
     unsigned short temp;
     I2C_Master_Wait();
     SSPCON2.RCEN = 1;
     I2C_Master_Wait();
     temp = SSPBUF;
     I2C_Master_Wait();
     if(a==1){SSPCON2.ACKDT=1;}
     else{SSPCON2.ACKDT=0;}
     SSPCON2.ACKEN = 1;
     return temp;
    }



    void main()
    {
     I2C_Master_Init(100000); //Initialize I2C Master with 100KHz clock
     Delay_ms(500);
     while(1)
     {
     I2C_Master_Start(); //Start condition
     I2C_Master_Write(0x30); //7 bit address + Write
    // I2C_Master_Write(0x00); //Write data
     //I2C_Master_Write(0x00);
     I2C_Master_Stop(); //Stop condition
     Delay_ms(2000);
     }
    }

El código completo para esclavo pic 18f4620

         //Slave pic 18f4620

//##############################################################################
unsigned short int zed=0;
volatile unsigned short int new =0 ,dataRead=0 , dataWrite=0;
unsigned char dataReadCh[7] , dataWriteCh[7];
//##############################################################################
void interrupt()
{
 if(PIR1.SSPIF == 1)
 {
  SSPCON1.CKP = 0;
  new=1;
 if ((SSPCON1.SSPOV) || (SSPCON1.WCOL))
 {
  zed = SSPBUF; // Read the previous value to clear the buffer
  SSPCON1.SSPOV = 0; // Clear the overflow flag
  SSPCON1.WCOL = 0; // Clear the collision bit
  SSPCON1.CKP = 1;
 }
 if((!SSPSTAT.D_A||SSPSTAT.D_A) && !SSPSTAT.R_W)
 {
  while(!SSPSTAT.BF){};
  while(SSPSTAT.BF){dataRead = SSPBUF;}
  SSPCON1.CKP = 1;
 }
 else if((!SSPSTAT.D_A||SSPSTAT.D_A) && SSPSTAT.R_W)
 {
  while(SSPSTAT.BF){zed = SSPBUF;}
  SSPBUF = dataWrite ;
  SSPCON1.CKP = 1;
  while(SSPSTAT.BF){};
 }
 PIR1.SSPIF = 0;
 }
}
//##############################################################################
void I2C_Slave_Init(unsigned short int address)
{
 SSPSTAT = 0b10000000;
 SSPADD = address;
 SSPCON1 = 0b00110110;
 SSPCON2 = 0b00000001;
 TRISC.B3 = 1; //Setting as input as given in datasheet
 TRISC.B4 = 1; //Setting as input as given in datasheet
 TRISC.B0=1;
 TRISC.B1=1;TRISC.B2=1;TRISC.B5=1;TRISC.B6=1;TRISC.B7=1;
 INTCON = 0b00000000;
 INTCON.PEIE = 1;
 INTCON.GIE = 1;
 PIE1.SSPIE = 1;
 PIR1.SSPIF = 0;
 while(SSPSTAT.BF){zed = SSPBUF;SSPCON1.SSPOV = 0;SSPCON1.WCOL = 0;}
}
//##############################################################################

void main() 
{
 ADCON1=0b00001111;
 TRISA.B0 = 0; //PORTD as output
 PORTA.B0=0;
 I2C_Slave_Init(0x18); //Initialize as a I2C Slave with address 0x30
 while(1)
 {
  if(new==1)
  {
   PORTA.B0=1;
   new=0;
  }
 }
}

Utilizo ese código tanto en " simulador de protues 8.0 " como en tableros reales 18f6420

Nuncaobtengounareaccióndelesclavocomosinoexistiera,siempreobtengounaseñal"notACK" que no se sabe es del Maestro o una respuesta del esclavo, pero estoy seguro de que "PIR1.SSPIF" nunca se vuelve igual a 1, ya que una vez que esto ocurra después de que ocurra una interrupción de MSSP, el valor de la variable llamada "nuevo" será igual a 1 y el LED en PORTA.B0 se iluminará

EsteLaimagencontienelaondadelosciloscopioquemuestralaseñal"NO ACK" en el noveno BIT

Entonces, cualquier ayuda, por favor, o cualquier edición en mi código que pueda sugerir para que funcione, por favor

Nota : cuando cambio SSPMx a 1110 en lugar de 0110, se produce la interrupción del MSSP esclavo y PIR1.SSPIF se convierte en 1. El LED de PORTA.B0 se ilumina de manera que el esclavo se interrumpe con éxito en el bit de paro de inicio, pero no con el envío de bytes de direcciones ni con la Llamada general, ya que traté de habilitar la llamada general y el envío de 0x00h, pero al final recibí la señal "NO ACK" / p>

  

SSPM3: SSPM0: bits de selección del modo de puerto serie síncrono maestro (2)

     

1111 = Modo esclavo I2C, dirección de 10 bits con bit de inicio y parada   interrupciones habilitadas

     

1110 = Modo esclavo I2C, dirección de 7 bits con bit de inicio y parada   interrupciones habilitadas

     

1011 = Modo maestro controlado por firmware I2C (Slave inactivo)

     

1000 = Modo maestro I2C, reloj = FOSC / (4 * (SSPADD + 1))

     

0111 = Modo esclavo I2C, dirección de 10 bits

     

0110 = Modo esclavo I2C, dirección de 7 bits

    

1 respuesta

0

Cambie R1 y R2 Tire de la resistencia 1000 ohms a 4.7komh's Ese es el primer problema en su circuito, otra cosa es asegurarse de que su cableado sea preciso y esté conectado

Agregue un pequeño retraso entre los datos de la dirección de inicio y la parada para la depuración y use el depurador i2c en Proteus para comprobar dónde está bloqueado su microcontrolador

1000 = Modo maestro I2C, reloj = FOSC / (4 * (SSPADD + 1)) Usa este modo

    
respondido por el bhura112

Lea otras preguntas en las etiquetas