SparkFun Forums 

Where electronics enthusiasts find answers.

Have questions about a SparkFun product or board? This is the place to be.
By aleph_null
#113033
Hello folks, I'm having issues connecting a pic microcontroller to the itg-3200 gyro using I2C.
I want to read the gyro's address (reg0) to ensure the I2C communication works, but am getting inconsistent results.
The address occasionally reads correctly, but most of the time the I2C read function does not work because of a bus collision: when this happens, PIR2bits.BCLIF is 1. What could cause this error?

Here is the code I have to read a register from I2C:
Code: Select all
char readRegister(unsigned char regNumber)
{
	unsigned char regValue, err;
	StartI2C();
	while ( SSPCON2bits.SEN );  // wait for start condition to end

	if( PIR2bits.BCLIF )         // test for bus collision                               
                    return( -1 );   
	// ITG address + Write bit
	
	if((err = WriteI2C(0b11010000)) != 0)
		return err;
	// Write register to read from
	
	if((err=WriteI2C(regNumber)) != 0)
		return err;
	RestartI2C();
	while( SSPCON2bits.RSEN );

	// ITG address + Read bit
	
	if((err=WriteI2C(READ_FROM_ITG)) != 0)
		return err;

	// read reg[regNumber]
	regValue = ReadI2C();
		
	IdleI2C();
	NotAckI2C();
	while( SSPCON2bits.ACKEN ); 

	StopI2C();
	while( SSPCON2bits.PEN ); 

	return regValue;
}
User avatar
By itikhonov
#113116
Are you sure that it's not the wiring? Are pull-ups ok? Have you tried at low baud rate?

BCL means that SCL/SDA already grounded before pic has a chance to send something, so check them with voltmeter.
By aleph_null
#113188
thanks!

It turns out some pins in port B were set to analog... so the SCL and SDA pins would read low even regardless of the voltage they had.

I can now read and write from and to the itg-3200. However, my program occassionally crashes on "WriteI2C". Upon further debugging, I found that the infinite loop while( SSPSTATbits.BF ); never end. this error only happens sometimes. Do you know what it could be?
User avatar
By itikhonov
#113201
aleph_null wrote:thanks!
I can now read and write from and to the itg-3200. However, my program occassionally crashes on "WriteI2C". Upon further debugging, I found that the infinite loop while( SSPSTATbits.BF ); never end. this error only happens sometimes. Do you know what it could be?
Probably you should wait for ACK after write.
By aleph_null
#113254
Yes, the WriteI2c function checks for an ACK. However, it doesn't reach that part of the code as it crashes while waiting for the SSPSTAT BF flag to clear, which should signal the end of transmission. The code just endlessly waits for the BF flag to clear, and it never does. why could that happen?
User avatar
By itikhonov
#113274
aleph_null wrote:Yes, the WriteI2c function checks for an ACK. However, it doesn't reach that part of the code as it crashes while waiting for the SSPSTAT BF flag to clear, which should signal the end of transmission. The code just endlessly waits for the BF flag to clear, and it never does. why could that happen?
Could you show your WriteI2C function? And that function where BF waiting is.
By aleph_null
#113327
Here's the code. It's basically the code from c18's peripheral library. Occasionally, this function will work and the correct value will be written to and from the gyro... but it freezes sooner or later.
Code: Select all
unsigned char WriteI2C( unsigned char data_out )
{
  SSPBUF = data_out;           // write single byte to SSPBUF
  if ( SSPCON1bits.WCOL )      // test if write collision occurred
     return ( -1 );              // if WCOL bit is set return negative #
  else
  {
     while( SSPSTATbits.BF );   // wait until write cycle is complete   CODE FREEZES HERE
     IdleI2C();                 // ensure module is idle
     if ( SSPCON2bits.ACKSTAT ) // test for ACK condition received
         return ( -2 );			// return NACK
     else 
          return ( 0 );              //return ACK
   }
}
User avatar
By itikhonov
#113332
Well, this can be due to clock arbitration (read 19.4.7.1 of manual). In short pic releases SCL line to high state and then actually checks that it goes high before transmitting next bit. So if gyro (or gremlins) shorts it ground it stops.

Measure what's on SCL when it freezes. And lower baud rate (to check for gremlins).

Btw, there is a bug in B6 and B7 revisions of chip (#40 - In I2C Master mode, narrow clock width upon slave clock stretch) but this should not affect things this way.
By aleph_null
#113338
Well thanks! You're right, the SCL line freezes with a value of 0 during these crashes.
However, even if I disconnect the gyro's SCL line after this happens, the microcontroller's SCL value is still 0. It seems as if the microcontroller is driving the SCL line to 0 and not the gyro.

Any thoughts?
By aleph_null
#113343
you must make the 2 I2C lines as outputs, clear LATC, then set them as inputs, then configure I2C registers as you normally would
hmm that seems to have made a difference. Very strange.


thank you for your help, itikhonov!
User avatar
By itikhonov
#113349
aleph_null wrote:
you must make the 2 I2C lines as outputs, clear LATC, then set them as inputs, then configure I2C registers as you normally would
hmm that seems to have made a difference. Very strange.


thank you for your help, itikhonov!
Crap. I am going to interface PIC18F4550 to MPR121 touch sensor soon so you just solved my not yet even happened problem :)
By balvi
#126603
Hi,

I am trying to connect the ITG-3200 to the the PIC. However I am having trouble setting up the connection. Could somebody tell me to which values I should set the I2CXBRG, and I2CXCON registers.


Thank you so much,

balvi