This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I2C Issue with HMC5883

Other Parts Discussed in Thread: HALCOGEN, RM46L852, PCA9515

Hello,

I'm having difficulties communicating over I2C with a digital compass (HMC5883). I have I2C setup as follows in Halcogen (version 4.04 with the i2c set mode bug fix).

I'm using the following code to read register 10 on the HMC5883. For reference a link to the datasheet is given below.
www51.honeywell.com/.../HMC5883L_3-Axis_Digital_Compass_IC.pdf

#define HMC5883_ADDR 0x1E

i2cInit();

i2cSetSlaveAdd(i2cREG1, HMC5883_ADDR);
i2cSetDirection(i2cREG1, I2C_TRANSMITTER);
i2cSetCount(i2cREG1, 1);
i2cSetMode(i2cREG1, I2C_MASTER);
i2cSetStop(i2cREG1);
i2cSetStart(i2cREG1);
i2cSendByte(i2cREG1, 0x10);
while(i2cIsBusBusy(i2cREG1) == true);
while(i2cIsStopDetected(i2cREG1) == 0);
i2cClearSCD(i2cREG1);

i2cSetSlaveAdd(i2cREG1, HMC5883_ADDR);
i2cSetDirection(i2cREG1, I2C_RECEIVER);
i2cSetCount(i2cREG1, 1);
i2cSetMode(i2cREG1, I2C_MASTER);
i2cSetStop(i2cREG1);
i2cSetStart(i2cREG1);
uint8 data = i2cReceiveByte(i2cREG1);
while(i2cIsBusBusy(i2cREG1) == true);
while(i2cIsStopDetected(i2cREG1) == 0);
i2cClearSCD(i2cREG1);

The program never makes it out of the first 

while(i2cIsBusBusy(i2cREG1) == true);

Any help would be appreciated, thanks.

  • Hi Jordan,

    I am not sure which Hercules microcontroller you are using, but I have following questions which will help in resolving the issue.

    1) Have you configured the PINMUX Tab to select I2C. ( If Not please go to PINMUX Tab in HALCoGen and Choose I2C check box on the TOP).

    2) Is the Hardware connection between Hercules and HMC done as per recommendation. Do they have common Ground?. If you are using Hercules HDK boards the Pull up is already available on the I2C bus, you need not have external pull. 

    3) Reading Page 11 of the HMC document, it mentions to read address register 10, you must write 0x3C followed by 0xA, but I see that you are writing 0x10 using i2csendByte API.

  • Hi Prathap, thank you for your reply.

    I've actually made some progress since I posted this yesterday. Originally I couldn't talk to the slave at all. I added a 350ms delay between when the slave device powers up and when I initialize the i2c peripheral. This allowed me to communicate with the slave.

    I have a 50 Hz loop in which I read and write to the device. Depending on how busy the loop is I'm able to read and write for a few seconds to 10s of seconds. The following actions have helped improve the performance.

    1. I added a small delay (10 us) after each set of commands.
    2. I enabled the RX and TX interrupts which prevented getting stuck in the TX & RX check infinite loops in the send and receive commands.

    I still have the problem that after some time (10s of seconds) I get stuck in either of the following.

    while(i2cIsBusBusy(i2cREG1) == true);
    while(i2cIsStopDetected(i2cREG1) == 0);

    In reference to your questions:

    1. I'm using the RM46L852 which has dedicated I2C pins.
    2. I have external 2.2k pull ups and am also using an I2C buffer (PCA9515). I've attached the schematic below for reference.
    3. The address device is 0x1E which corresponds to a write address of 0x3C and a write address of 0x3D. I'm writing a decimal 10 (0xA) not 0x10.