i2c not working

Thread Starter

kingsloth

Joined Dec 28, 2015
12
i'm trying to read values with the following routine

C:
void read()
{
  unsigned int lsb = 0;
  unsigned char msb = 0;
  char str[20];

  if (I2CBusIsIdle(I2C1))
  {
  I2CStart(I2C1);
  }

  I2CSendByte(I2C1, REG_WRITE);
  IdleI2C1();
  I2CSendByte(I2C1, DATA_OUTPUT_X);
  IdleI2C1();
  I2CRepeatStart(I2C1);
  IdleI2C1();
  I2CSendByte(I2C1,REG_READ);
  IdleI2C1();

  I2CReceiverEnable(I2C1, TRUE);

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  X_axis=((msb<<8) | lsb);
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  Z_axis=((msb<<8) | lsb);
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();


  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, FALSE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  Y_axis=((msb<<8) | lsb);


  I2CStop(I2C1);

}
I always get 0.0, what am i doing wrong? I have SDA on pin RG3 and SCL on RG2, both with a resistence of 4k7 to 3.3V.

Moderators note : used code tags for C
 
Last edited:

sailorjoe

Joined Jun 4, 2013
364
What i2c library are you using, please?
Since I don't have the library information, I'm just guessing here. At line 24, consider what happens if no data is available. Does the i2c function I2CReceivedDataIsAvailable() wait for data, or return false if data hasn't arrived yet?
 

spinnaker

Joined Oct 29, 2009
7,830
i'm trying to read values from hmc5833l with the following routine

C:
void read()
{
  unsigned int lsb = 0;
  unsigned char msb = 0;
  char str[20];

  if (I2CBusIsIdle(I2C1))
  {
  I2CStart(I2C1);
  }

  I2CSendByte(I2C1, REG_WRITE);
  IdleI2C1();
  I2CSendByte(I2C1, DATA_OUTPUT_X);
  IdleI2C1();
  I2CRepeatStart(I2C1);
  IdleI2C1();
  I2CSendByte(I2C1,REG_READ);
  IdleI2C1();

  I2CReceiverEnable(I2C1, TRUE);

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  X_axis=((msb<<8) | lsb);
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  Z_axis=((msb<<8) | lsb);
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();


  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, TRUE);
  msb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  I2CReceiverEnable(I2C1, TRUE);
  IdleI2C1();

  if (I2CReceivedDataIsAvailable(I2C1))
  {
  I2CAcknowledgeByte(I2C1, FALSE);
  lsb = I2CGetByte(I2C1);
  }
  IdleI2C1();
  Y_axis=((msb<<8) | lsb);


  I2CStop(I2C1);

}
I always get 0.0, what am i doing wrong? I have SDA on pin RG3 and SCL on RG2, both with a resistence of 4k7 to 3.3V. IF i use pic32 i still need to read to msb and lsb and then do the shift?(i just followed what i read on hmc data sheet)

Moderators note : used code tags for C
Have you scoped the output of the mcu to see if you are even putting out data?
 

Thread Starter

kingsloth

Joined Dec 28, 2015
12
What i2c library are you using, please?
Since I don't have the library information, I'm just guessing here. At line 24, consider what happens if no data is available. Does the i2c function I2CReceivedDataIsAvailable() wait for data, or return false if data hasn't arrived yet?
It only returns true or false.
 
Last edited:

Thread Starter

kingsloth

Joined Dec 28, 2015
12
From where you got the library for MPlab
don't know if i'm doing it right or not but i just pressed F1 (help) and there was a bunch of routines to use i2c, i just read them and use them. It compiled so i thought i was doing good. I'm trying to re-write the code making my own i2c functions, maybe it will work...
 

spinnaker

Joined Oct 29, 2009
7,830
I'm using MPLAB X so i'm just using their library. It only returns true or false.

MPLabX is not a compiler it is a development enviroment.. What compiler are you using? It isn't XC8 because the documentation does not match your calls unless you are using your own wrapper around the XC8 calls. So which is it?
 

spinnaker

Joined Oct 29, 2009
7,830
This is the only thing i get, ch1 - SCL ch2- SDA.
This is good. At least something is coming out. Can you see if you are getting a response from the slave? You don't happen to have a logic analyzer? They can be a huge hel in situations like this.

Next thing to check after that is all of your settings are the way you need them
 

ErnieM

Joined Apr 24, 2011
8,377
The scope picture looks perfect for the address to write to this device, and since the 9th bit is zero the slave is acknowledging it is being addressed. Doesn't get any better than that.

The next step is to grab an entire write sequence and then the read sequence. See if things keep jetting that nice ACK bit set. And don't forget when reading multiple bytes your master pic must do the ACK, your lib has that function.

Getting these low level transactions to all play together is a major piece of my debugging time. The good news is you have a scope as a reality check.

I would strongly suggest you find some example code on the interwebs where someone shows the sequence that worked for them to bang this device. I am not sure how I would do it after peeking at the operational examples of the device data sheet.
 

spinnaker

Joined Oct 29, 2009
7,830
The scope picture looks perfect for the address to write to this device, and since the 9th bit is zero the slave is acknowledging it is being addressed. Doesn't get any better than that.

The next step is to grab an entire write sequence and then the read sequence. See if things keep jetting that nice ACK bit set. And don't forget when reading multiple bytes your master pic must do the ACK, your lib has that function.

Getting these low level transactions to all play together is a major piece of my debugging time. The good news is you have a scope as a reality check.

I would strongly suggest you find some example code on the interwebs where someone shows the sequence that worked for them to bang this device. I am not sure how I would do it after peeking at the operational examples of the device data sheet.
Wow that is where experience pays off! :)


The XC8 manual has examples. But as I mention this is not XC8 unless is it is a wrapper. What confuses me id there is no configuration in the code as posted.
 

Thread Starter

kingsloth

Joined Dec 28, 2015
12
Thing is the only thing i got from the scope was that, nothing more, so probably it's only writing to device, never reads it
 

ErnieM

Joined Apr 24, 2011
8,377
Oh bleep, spinnaker talks me up then I have to take it back.

Most of the transmission looks ok, but the address should begin with a START transaction, which is SCL hi while SDA goes low. If you only see this pattern over and over the sequence never sends a STOP signal.

I am typing on a silly iPad and can't copy and paste code. If I was doing this I would forget all that code you have and begin with a simple config command, which btw I do not see in your code, do you initial the device?

One trick is to use a spare I/O pin as a flag, set it hi when you start a transaction and set lo when done. This gives you a solid signal to trigger your (very nice) scope.
 

Thread Starter

kingsloth

Joined Dec 28, 2015
12
Oh bleep, spinnaker talks me up then I have to take it back.

Most of the transmission looks ok, but the address should begin with a START transaction, which is SCL hi while SDA goes low. If you only see this pattern over and over the sequence never sends a STOP signal.

I am typing on a silly iPad and can't copy and paste code. If I was doing this I would forget all that code you have and begin with a simple config command, which btw I do not see in your code, do you initial the device?

One trick is to use a spare I/O pin as a flag, set it hi when you start a transaction and set lo when done. This gives you a solid signal to trigger your (very nice) scope.

yeah im doing:

I2CSetFrequency(I2C1, FPB, FSCK); // it gives 100kHz, thats right
I2CEnable(I2C1, TRUE);

To me looks like the problem is I2CStop(I2C1) isn't working, dont know how to solve it though.
 
Top