problemas para que dos PIC se comuniquen a través de I2C

1

Tengo algunos problemas para que dos PIC se comuniquen entre sí a través de una línea I2C. Ambos son 16F886, uno sentado en el tablero de demostración PIC de 28 pines, el segundo está dentro de un tablero que diseñé para un propósito diferente pero tratando de usarlo para crear prototipos de esta configuración. Estoy tratando de hacer que se comuniquen con un código muy simple, sin embargo, estoy obteniendo un resultado incorrecto en el lado esclavo. Cuando alcance el SDA / SCL, obtengo una lectura correcta de la dirección, y el esclavo parece estar activando el byte de la dirección (aunque parece que una de las secuencias no se está ejecutando correctamente). Por el valor de la lectura, pensé que esto se debe a que el SDA no se ha bajado a tiempo debido a valores de resistencia incorrectos en la línea (??)

Código maestro:

#define _XTAL_FREQ 4000000 
#include<htc.h>
#include<stdio.h>
#include<stdlib.h>

#include "i2c_sim.h"
__CONFIG(FOSC_INTRC_CLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & CP_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF); 



void main(void)
{
OSCCON = 0b01100111;
I2CInit();

unsigned char data=5;

while(1){
I2CStart();
i2c_dly();
I2CSend( 0xB0 ); //send address
i2c_dly();
i2c_dly();
I2CSend( 0x0 ); //send data
i2c_dly();
I2CStop();
__delay_us(50);

}
}

Función de inicio I2C

void I2CInit(void)
{
TRISC3 = 1; /* SDA and SCL as input pin */
TRISC4 = 1; /* these pins can be configured either i/p or o/p */
SSPSTAT |= 0x80; /* Slew rate disabled */
SSPCON = 0x28; /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
SSPADD = 0x28 ;/*0x28= 100Khz @ 4Mhz Fosc */ //==31 with 20mhz
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;
}

Código de esclavo

#define _XTAL_FREQ 4000000 
#include<htc.h>
#include<stdio.h>
#include<stdlib.h>

#include "i2c_sim.h"
#include "uart.h"
__CONFIG(FOSC_INTRC_CLKOUT & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & CP_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF); 


void main(void)
{
OSCCON = 0b01100111;
UART_Init(4800);
I2CInit();

SSPADD = 0xB0; //SSPADD contains I2C device address in SLAVE mode

unsigned char data=5;
while(1){
if(PIR1bits.SSPIF == 1)
    {
    UART_Write_Text("0,");  //this prints out just fine
    if(SSPSTATbits.BF == 1 && SSPSTATbits.D_A == 0) **this block is never entered**
        { 
            //PIR1bits.SSPIF = 0;
            unsigned char addr = I2CRead(1);//read with ack
            i2c_dly();
            data = I2CRead(0); //read nack
            i2c_dly();
            UART_Write_Text("1,");
        }
    data = SSPBUF;
    SSPSTATbits.BF = 0;
    char str[12];
    sprintf(str,"%d",data);
    UART_Write_Text("*");
    UART_Write_Text(str); //yields 254 constantly
    UART_Write_Text("*");
    SSPSTATbits.D_A = 0;
    }


    }
    }

I2C Slave init

void I2CInit(void)
{
TRISC3 = 1; /* SDA and SCL as input pin */
TRISC4 = 1; /* these pins can be configured either i/p or o/p */
SSPSTAT |= 0x80; /* Slew rate disabled */
SSPCON = 0x28; /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
SSPADD = 0x31 ;/*0x28= 100Khz @ 4Mhz Fosc */ //==31 with 20mhz
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;
}

alcance ...

    
pregunta Elad N

1 respuesta

2

[SOLVED◆

Bueno, después de intentar rastrear el problema por algún tiempo, he encontrado mis principales errores:

  • Debido a mi falta de conocimiento con I2C, he usado una función de lectura maestra para leer los datos; en PIC16F886 I2C se maneja con hardware : solo lea el SSPBUF y obtendrá sus datos. Además, esa función de Lectura en realidad estaba intentando bajar el reloj (como se supone que debe hacer el maestro), desde el lado del esclavo (por lo tanto, la tensión se redujo a casi 0 = > sin reloj).
  • Los valores de la resistencia aparentemente eran incorrectos: el voltaje en SDA fue inferior al especificado en las especificaciones I2C.

Intentaré publicar un tutorial sobre este problema con el código para XC8 ASAP. Saludos

    
respondido por el Elad N

Lea otras preguntas en las etiquetas