1
\$\begingroup\$

This question already has an answer here:

Duplicate question was also asked by me and the current question has different code

I have a PIC32 starter kit and I am making I2C communication with DS1307 RTC. I have used the functions for I2C Communiation described in this document page no- 221. I am using MPLAB 8 with watch window opened and added all the register of I2C in watch window, so that when I debug my code, I can see which register has what value. Following is my code:

#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;
}

For the time being I am just trying to set date and read it back.

1) My first problem is that, when I start debugging, in INIT I2C after IdleI2C1(); I2C1STAT (register which gives the status of I2C ) gives value 0x400 which means 10th bit is 1 and if we look into the bits of this register then it says:

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

So this means that collision has been detected. But i havent send anything then why it is saying that collision has been detected.?

2) MasterWrite() function is running properly, because when ever this command is executed, i can see the change in I2C1TRN register(this displays the transmitted data) and the values of i j k changes to 0 because MasterWrite() returns 0 whenever the data is transmitted successfully. But when my control reaches the GetDate it doesnt enter because no data is available. So my second question is that when my data is transmitted successfully, why I am not getting any data back??

Any Pic experts please help me with I2C communication. Thanks!

\$\endgroup\$

marked as duplicate by Daniel Grillo, Dave Tweed Aug 24 '15 at 14:42

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ yeah thats my question but I have changed the code. \$\endgroup\$ – Aircraft Aug 22 '15 at 11:53
  • 1
    \$\begingroup\$ Do you have pull-ups on both lines for sure? If your SDA line is not pulled high properly, the PIC would see that as a bus collision. \$\endgroup\$ – justing Aug 22 '15 at 17:00
  • \$\begingroup\$ No I dont have pull up resistor. Looks like I'll have to make my own circuit for this. can you tell me schematic for DS1307. I have found this circuit: cdn.sparkfun.com/datasheets/BreakoutBoards/RTC-Module.v14.pdf . Is it good enough for communication \$\endgroup\$ – Aircraft Aug 24 '15 at 4:14
  • 1
    \$\begingroup\$ Adding pull-up resistors is a necessity in I2C communication. Their values are critical. I tried DS1307 + AVR 16Mhz does not work properly with 10k, works with 1k8 ohm \$\endgroup\$ – Oka Aug 24 '15 at 8:43
  • \$\begingroup\$ You should have edited your original question rather than starting a new one. \$\endgroup\$ – Dave Tweed Aug 24 '15 at 14:41
-1
\$\begingroup\$

If you don't have external pull-up resistors as mentioned in the comments, you can try to enable the internal pull-ups - it's hard to find an actual value on them, but if the quoted 50µA in the data sheet are related to the pull-ups they would be around \$66k\Omega\$. Those values are a bit high, but with a slow I²C clock they should be fine. Outside of the official I²C specification, so no guarantee they will work, have a look at page 55.

To enable those you can use the change notification functions of the peripheral library (here) on the SDA and SCL pins. I'm not 100% sure if that will work (not a PIC expert), the description of the I²C module sounds like it could override all I/O pin settings (here):

Enabling I 2 C I/O

Two pins are used for bus operation: the SCLx pin, which is the clock, and the SDAx pin, which is the data. When the I 2 C module is enabled, assuming no other module with higher priority has control, the module will assume control of the SDAx and SCLx pins. The module software need not be concerned with the state of the port I/O of the pins, the module overrides, the port state, and direction. At initialization, the pins are tri-state (released).

Even if that works, putting external pull-up resistors is recommended as you can change the value if your I²C bus grows larger or you have noise issues.

The schematic you posted in your comment is fine (note: C1 is used as a decoupling capacitor for the RTC supply pin, and should be placed as closely to the pin as possible). I wonder what kind of connection / schematic you used until now.

\$\endgroup\$
  • \$\begingroup\$ Please help me improve my answer by pointing out wrong parts instead of just downvoting. Thank you. \$\endgroup\$ – Arsenal Aug 24 '15 at 9:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.