Comunicación de error en I2C en PIC32 [duplicado]

1

También hice una pregunta duplicada y la pregunta actual tiene un código diferente

Tengo un PIC32 starter kit y estoy haciendo comunicación I2C con DS1307 RTC . He usado las funciones para I2C Communiation descritas en este documento página no- 221. Soy El uso de MPLAB 8 con la ventana de visualización abierta y agregó todo el registro de I2C en la ventana de vigilancia, de modo que cuando depuro mi código, puedo ver qué registro tiene qué valor. El siguiente es mi código:

#include <plib.h>

#define SYSTEM_FREQUENCY            72000000L
#pragma config FNOSC = PRIPLL       //Primary Osc w/PLL (XT+,HS+,EC+PLL)
#pragma config POSCMOD = HS         //HS osc mode 
#pragma config FPLLMUL = MUL_18     //PLL Multiplier 18x Multiplier 
#pragma config FPLLIDIV = DIV_2     //PLL Input Divider 2x Divider 
#pragma config FPBDIV = DIV_1       //Peripheral Clock Divisor: Pb_Clk is Sys_Clk/2
#pragma config FPLLODIV = DIV_1     //System PLL Output Clock Divider: PLL Divide by 1
#pragma config FWDTEN = OFF         //WatchDog Timer

#define CCLK  (60000000)
#define PBCLK (CCLK/8)

#define Fsck 375000
#define BRG_VAL (PBCLK/2/Fsck)

int main()
{
  mOSCSetPBDIV (OSC_PB_DIV_8);

  OpenI2C1( I2C_EN, BRG_VAL );


  //*********INIT I2C************// 
  StartI2C1();
  IdleI2C1();    //This function generates Wait condition until I2C bus is Idle.
  MasterWriteI2C1(0xD0);  //Address of DS1307
  MasterWriteI2C1(0x07);
  MasterWriteI2C1(0x00);
  AckI2C1();    
  StopI2C1();
  IdleI2C1();
  //*********INIT I2C END**********//


  //**********SET DATE**********//  
  int i=5, j =5, k =5;
  StartI2C1();
  IdleI2C1();
  MasterWriteI2C1(0xD0);
  MasterWriteI2C1(0x04);
  i = MasterWriteI2C1(0x19);
  j = MasterWriteI2C1(0x10);
  k = MasterWriteI2C1(0x09);
  AckI2C1();        
  StopI2C1();
  IdleI2C1();
  //*********SET DATE END*********//


  //**********GET DATE************//
  if(I2C1STATbits.RBF == 1)   //if data is available
  {
   StartI2C1();
   IdleI2C1();
   MasterWriteI2C1(0xD0);
   AckI2C1();   
   IdleI2C1();
   StopI2C1();
   IdleI2C1();

   unsigned char val1 = 5;
   unsigned char val2 = 5;
   unsigned char val3 = 5;
   StartI2C1();                
    MasterWriteI2C1(0xD1);      
   val1 = MasterReadI2C1();
   val2 = MasterReadI2C1();
   val3 = MasterReadI2C1();
   AckI2C1();   

   StopI2C1();
   IdleI2C1();
}
if(I2C1STATbits.RBF == 0)    //if data is not available
{

}
return 0;
}

Por el momento, solo estoy tratando de establecer la fecha y leerla nuevamente.

1) Mi primer problema es que, cuando comienzo a la depuración, en INIT I2C después de IdleI2C1(); I2C1STAT (registro que da el estado de I2C) da el valor 0x400 , lo que significa que el décimo bit es 1 y si miramos los bits de este registro entonces dice:

bit 10:
  BCL: Master Bus Collision Detect bit
  Cleared when the I2C module is disabled (ON = 0).
  1 =A bus collision has been detected during a master operation
  0 =No collision has been detected

Esto significa que se ha detectado una colisión. Pero no he enviado nada, entonces ¿por qué dice que se ha detectado una colisión?

2) La función MasterWrite() se ejecuta correctamente, porque siempre que se ejecuta este comando, puedo ver el cambio en el registro I2C1TRN (esto muestra los datos transmitidos) y los valores de ijk cambian a 0 porque MasterWrite() devuelve 0 siempre que los datos se transmitan con éxito. Pero cuando mi control alcanza el GetDate no se ingresa porque no hay datos disponibles. Entonces, mi segunda pregunta es que cuando mis datos se transmiten con éxito, ¿por qué no estoy recuperando ningún dato?

Cualquier experto en fotografía, por favor, ayúdame con la comunicación I2C. Gracias!

    
pregunta Aircraft

1 respuesta

-1

Si no tiene resistores de pull-up externos como se menciona en los comentarios, puede intentar habilitar los pull-ups internos; es difícil encontrar un valor real en ellos, pero si comentado 50µA en la hoja de datos están relacionados con los dominios que serían alrededor de \ $ 66k \ Omega PS Esos valores son un poco altos, pero con un reloj I²C lento deberían estar bien. Fuera de la especificación oficial de I²C , por lo que no hay garantía de que funcionen, consulte la página 55.

Para habilitarlas, puede usar las funciones de notificación de cambios de la biblioteca periférica ( aquí ) en los pines SDA y SCL. No estoy 100% seguro de si eso funcionará (no soy un experto en PIC), la descripción del módulo I²C parece que podría anular todas las configuraciones de los pines de E / S (here ):

  

Habilitando I 2 C I / O

     

Se usan dos pines para la operación de bus: el pin SCLx, que es el reloj, y el pin SDAx, que   es el dato Cuando el módulo I 2 C está habilitado, suponiendo que no haya otro módulo con mayor prioridad tiene   control, el módulo asumirá el control de los pines SDAx y SCLx. El módulo de software necesita.   no se preocupe por el estado de la E / S del puerto de los pines, las modificaciones del módulo, el estado del puerto,   y dirección. En la inicialización, los pines son tri-state (liberados).

Incluso si eso funciona, se recomienda colocar resistores de pull-up externos, ya que puede cambiar el valor si su bus I²C aumenta de tamaño o si tiene problemas de ruido.

El esquema que publicó en su comentario está bien (nota: se usa C1 como un condensador de desacoplamiento para el pin de alimentación RTC, y debe colocarse lo más cerca posible del pin). Me pregunto qué tipo de conexión / esquema usaste hasta ahora.

    
respondido por el Arsenal

Lea otras preguntas en las etiquetas